From bf530b621403d1f0e27abf415ec1ae7fd743e266 Mon Sep 17 00:00:00 2001 From: Sweetbread Date: Sat, 12 Sep 2026 00:29:36 +0300 Subject: [PATCH] ref: db --- app/src/main/java/ru/sweetbread/unn/UNNApp.kt | 2 +- .../ru/sweetbread/unn/{ => core}/db/DB.kt | 17 +- .../unn/core/db/dao/AuditoriumDao.kt | 22 ++ .../sweetbread/unn/core/db/dao/BuildingDao.kt | 22 ++ .../unn/core/db/dao/DisciplineDao.kt | 22 ++ .../unn/core/db/dao/KindOfWorkDao.kt | 22 ++ .../sweetbread/unn/core/db/dao/LecturerDao.kt | 22 ++ .../unn/core/db/{ => dao}/NewsDao.kt | 2 +- .../unn/core/db/dao/ScheduleItemDao.kt | 38 +++ .../ru/sweetbread/unn/core/db/dao/UserDao.kt | 21 ++ .../unn/core/db/entity/Auditorium.kt | 51 ++++ .../sweetbread/unn/core/db/entity/Building.kt | 21 ++ .../unn/core/db/entity/Discipline.kt | 22 ++ .../unn/core/db/entity/KindOfWork.kt | 28 ++ .../sweetbread/unn/core/db/entity/Lecturer.kt | 31 ++ .../ru/sweetbread/unn/core/db/entity/News.kt | 1 + .../unn/core/db/entity/ScheduleUnit.kt | 70 +++++ .../unn/core/db/entity/{UserDB.kt => User.kt} | 3 +- .../java/ru/sweetbread/unn/db/Schedule.kt | 269 ------------------ .../main/java/ru/sweetbread/unn/db/UserDB.kt | 74 ----- .../unn/feature/news/NewsRemoteMediator.kt | 2 +- .../unn/feature/news/NewsRepository.kt | 2 +- .../unn/feature/profile/UserRepository.kt | 2 +- .../feature/schedule/ScheduleRepository.kt | 6 +- 24 files changed, 418 insertions(+), 354 deletions(-) rename app/src/main/java/ru/sweetbread/unn/{ => core}/db/DB.kt (53%) create mode 100644 app/src/main/java/ru/sweetbread/unn/core/db/dao/AuditoriumDao.kt create mode 100644 app/src/main/java/ru/sweetbread/unn/core/db/dao/BuildingDao.kt create mode 100644 app/src/main/java/ru/sweetbread/unn/core/db/dao/DisciplineDao.kt create mode 100644 app/src/main/java/ru/sweetbread/unn/core/db/dao/KindOfWorkDao.kt create mode 100644 app/src/main/java/ru/sweetbread/unn/core/db/dao/LecturerDao.kt rename app/src/main/java/ru/sweetbread/unn/core/db/{ => dao}/NewsDao.kt (95%) create mode 100644 app/src/main/java/ru/sweetbread/unn/core/db/dao/ScheduleItemDao.kt create mode 100644 app/src/main/java/ru/sweetbread/unn/core/db/dao/UserDao.kt create mode 100644 app/src/main/java/ru/sweetbread/unn/core/db/entity/Auditorium.kt create mode 100644 app/src/main/java/ru/sweetbread/unn/core/db/entity/Building.kt create mode 100644 app/src/main/java/ru/sweetbread/unn/core/db/entity/Discipline.kt create mode 100644 app/src/main/java/ru/sweetbread/unn/core/db/entity/KindOfWork.kt create mode 100644 app/src/main/java/ru/sweetbread/unn/core/db/entity/Lecturer.kt create mode 100644 app/src/main/java/ru/sweetbread/unn/core/db/entity/ScheduleUnit.kt rename app/src/main/java/ru/sweetbread/unn/core/db/entity/{UserDB.kt => User.kt} (98%) delete mode 100644 app/src/main/java/ru/sweetbread/unn/db/Schedule.kt delete mode 100644 app/src/main/java/ru/sweetbread/unn/db/UserDB.kt diff --git a/app/src/main/java/ru/sweetbread/unn/UNNApp.kt b/app/src/main/java/ru/sweetbread/unn/UNNApp.kt index e4896a2..f5d7b8a 100644 --- a/app/src/main/java/ru/sweetbread/unn/UNNApp.kt +++ b/app/src/main/java/ru/sweetbread/unn/UNNApp.kt @@ -7,9 +7,9 @@ import android.content.Context import ru.sweetbread.unn.core.AuthRepository import ru.sweetbread.unn.core.CredentialsStore import ru.sweetbread.unn.core.SessionManager +import ru.sweetbread.unn.core.db.AppDatabase import ru.sweetbread.unn.core.network.PortalApi import ru.sweetbread.unn.core.network.createHttpClient -import ru.sweetbread.unn.db.AppDatabase import ru.sweetbread.unn.feature.news.NewsRepository import ru.sweetbread.unn.feature.profile.UserRepository import ru.sweetbread.unn.feature.schedule.ScheduleRepository diff --git a/app/src/main/java/ru/sweetbread/unn/db/DB.kt b/app/src/main/java/ru/sweetbread/unn/core/db/DB.kt similarity index 53% rename from app/src/main/java/ru/sweetbread/unn/db/DB.kt rename to app/src/main/java/ru/sweetbread/unn/core/db/DB.kt index f99f57c..2493d44 100644 --- a/app/src/main/java/ru/sweetbread/unn/db/DB.kt +++ b/app/src/main/java/ru/sweetbread/unn/core/db/DB.kt @@ -1,11 +1,24 @@ // Copyright (c) 2026 Gleb Zaharov. License: GPLv3 (see LICENSE). -package ru.sweetbread.unn.db +package ru.sweetbread.unn.core.db import androidx.room.Database import androidx.room.RoomDatabase -import ru.sweetbread.unn.core.db.NewsDao +import ru.sweetbread.unn.core.db.dao.AuditoriumDao +import ru.sweetbread.unn.core.db.dao.BuildingDao +import ru.sweetbread.unn.core.db.dao.DisciplineDao +import ru.sweetbread.unn.core.db.dao.KindOfWorkDao +import ru.sweetbread.unn.core.db.dao.LecturerDao +import ru.sweetbread.unn.core.db.dao.NewsDao +import ru.sweetbread.unn.core.db.dao.ScheduleItemDao +import ru.sweetbread.unn.core.db.dao.UserDao +import ru.sweetbread.unn.core.db.entity.AuditoriumDB +import ru.sweetbread.unn.core.db.entity.BuildingDB +import ru.sweetbread.unn.core.db.entity.DisciplineDB +import ru.sweetbread.unn.core.db.entity.KindOfWorkDB +import ru.sweetbread.unn.core.db.entity.LecturerDB import ru.sweetbread.unn.core.db.entity.NewsDB +import ru.sweetbread.unn.core.db.entity.ScheduleUnitDB import ru.sweetbread.unn.core.db.entity.UserDB @Database(entities = [ diff --git a/app/src/main/java/ru/sweetbread/unn/core/db/dao/AuditoriumDao.kt b/app/src/main/java/ru/sweetbread/unn/core/db/dao/AuditoriumDao.kt new file mode 100644 index 0000000..2778249 --- /dev/null +++ b/app/src/main/java/ru/sweetbread/unn/core/db/dao/AuditoriumDao.kt @@ -0,0 +1,22 @@ +// Copyright (c) 2026 Gleb Zaharov. License: GPLv3 (see LICENSE). + +package ru.sweetbread.unn.core.db.dao + +import androidx.room.Dao +import androidx.room.Delete +import androidx.room.Insert +import androidx.room.OnConflictStrategy +import androidx.room.Query +import ru.sweetbread.unn.core.db.entity.AuditoriumDB + +@Dao +interface AuditoriumDao { + @Query("SELECT * FROM auditoriumdb WHERE oid = :oid LIMIT 1") + suspend fun get(oid: Int): AuditoriumDB? + + @Insert(onConflict = OnConflictStrategy.REPLACE) + suspend fun insert(auditoriums: List) + + @Delete + fun delete(auditorium: AuditoriumDB) +} \ No newline at end of file diff --git a/app/src/main/java/ru/sweetbread/unn/core/db/dao/BuildingDao.kt b/app/src/main/java/ru/sweetbread/unn/core/db/dao/BuildingDao.kt new file mode 100644 index 0000000..28f460f --- /dev/null +++ b/app/src/main/java/ru/sweetbread/unn/core/db/dao/BuildingDao.kt @@ -0,0 +1,22 @@ +// Copyright (c) 2026 Gleb Zaharov. License: GPLv3 (see LICENSE). + +package ru.sweetbread.unn.core.db.dao + +import androidx.room.Dao +import androidx.room.Delete +import androidx.room.Insert +import androidx.room.OnConflictStrategy +import androidx.room.Query +import ru.sweetbread.unn.core.db.entity.BuildingDB + +@Dao +interface BuildingDao { + @Query("SELECT * FROM buildingdb WHERE oid = :oid LIMIT 1") + suspend fun get(oid: Int): BuildingDB? + + @Insert(onConflict = OnConflictStrategy.REPLACE) + suspend fun insert(buildings: List) + + @Delete + fun delete(building: BuildingDB) +} \ No newline at end of file diff --git a/app/src/main/java/ru/sweetbread/unn/core/db/dao/DisciplineDao.kt b/app/src/main/java/ru/sweetbread/unn/core/db/dao/DisciplineDao.kt new file mode 100644 index 0000000..e3dbb24 --- /dev/null +++ b/app/src/main/java/ru/sweetbread/unn/core/db/dao/DisciplineDao.kt @@ -0,0 +1,22 @@ +// Copyright (c) 2026 Gleb Zaharov. License: GPLv3 (see LICENSE). + +package ru.sweetbread.unn.core.db.dao + +import androidx.room.Dao +import androidx.room.Delete +import androidx.room.Insert +import androidx.room.OnConflictStrategy +import androidx.room.Query +import ru.sweetbread.unn.core.db.entity.DisciplineDB + +@Dao +interface DisciplineDao { + @Query("SELECT * FROM disciplinedb WHERE oid = :oid LIMIT 1") + suspend fun get(oid: Int): DisciplineDB? + + @Insert(onConflict = OnConflictStrategy.REPLACE) + suspend fun insert(disciplines: List) + + @Delete + fun delete(discipline: DisciplineDB) +} \ No newline at end of file diff --git a/app/src/main/java/ru/sweetbread/unn/core/db/dao/KindOfWorkDao.kt b/app/src/main/java/ru/sweetbread/unn/core/db/dao/KindOfWorkDao.kt new file mode 100644 index 0000000..2ea72c3 --- /dev/null +++ b/app/src/main/java/ru/sweetbread/unn/core/db/dao/KindOfWorkDao.kt @@ -0,0 +1,22 @@ +// Copyright (c) 2026 Gleb Zaharov. License: GPLv3 (see LICENSE). + +package ru.sweetbread.unn.core.db.dao + +import androidx.room.Dao +import androidx.room.Delete +import androidx.room.Insert +import androidx.room.OnConflictStrategy +import androidx.room.Query +import ru.sweetbread.unn.core.db.entity.KindOfWorkDB + +@Dao +interface KindOfWorkDao { + @Query("SELECT * FROM kindofworkdb WHERE oid = :oid LIMIT 1") + suspend fun get(oid: Int): KindOfWorkDB? + + @Insert(onConflict = OnConflictStrategy.REPLACE) + suspend fun insert(kindOfWork: List) + + @Delete + fun delete(kindOfWork: KindOfWorkDB) +} \ No newline at end of file diff --git a/app/src/main/java/ru/sweetbread/unn/core/db/dao/LecturerDao.kt b/app/src/main/java/ru/sweetbread/unn/core/db/dao/LecturerDao.kt new file mode 100644 index 0000000..472929f --- /dev/null +++ b/app/src/main/java/ru/sweetbread/unn/core/db/dao/LecturerDao.kt @@ -0,0 +1,22 @@ +// Copyright (c) 2026 Gleb Zaharov. License: GPLv3 (see LICENSE). + +package ru.sweetbread.unn.core.db.dao + +import androidx.room.Dao +import androidx.room.Delete +import androidx.room.Insert +import androidx.room.OnConflictStrategy +import androidx.room.Query +import ru.sweetbread.unn.core.db.entity.LecturerDB + +@Dao +interface LecturerDao { + @Query("SELECT * FROM lecturerdb WHERE unnId = :unnId LIMIT 1") + suspend fun get(unnId: Int): LecturerDB? + + @Insert(onConflict = OnConflictStrategy.REPLACE) + suspend fun insert(lecturers: List) + + @Delete + fun delete(lecturer: LecturerDB) +} \ No newline at end of file diff --git a/app/src/main/java/ru/sweetbread/unn/core/db/NewsDao.kt b/app/src/main/java/ru/sweetbread/unn/core/db/dao/NewsDao.kt similarity index 95% rename from app/src/main/java/ru/sweetbread/unn/core/db/NewsDao.kt rename to app/src/main/java/ru/sweetbread/unn/core/db/dao/NewsDao.kt index 4d7c7f1..ac5088a 100644 --- a/app/src/main/java/ru/sweetbread/unn/core/db/NewsDao.kt +++ b/app/src/main/java/ru/sweetbread/unn/core/db/dao/NewsDao.kt @@ -1,6 +1,6 @@ // Copyright (c) 2026 Gleb Zaharov. License: GPLv3 (see LICENSE). -package ru.sweetbread.unn.core.db +package ru.sweetbread.unn.core.db.dao import androidx.paging.PagingSource import androidx.room.Dao diff --git a/app/src/main/java/ru/sweetbread/unn/core/db/dao/ScheduleItemDao.kt b/app/src/main/java/ru/sweetbread/unn/core/db/dao/ScheduleItemDao.kt new file mode 100644 index 0000000..280b5ef --- /dev/null +++ b/app/src/main/java/ru/sweetbread/unn/core/db/dao/ScheduleItemDao.kt @@ -0,0 +1,38 @@ +// Copyright (c) 2026 Gleb Zaharov. License: GPLv3 (see LICENSE). + +package ru.sweetbread.unn.core.db.dao + +import androidx.room.Dao +import androidx.room.Delete +import androidx.room.Insert +import androidx.room.OnConflictStrategy +import androidx.room.Query +import kotlinx.coroutines.flow.Flow +import ru.sweetbread.unn.core.db.entity.ScheduleUnitDB + +@Dao +interface ScheduleItemDao { + @Query("SELECT * FROM scheduleUnitDB WHERE oid = :oid LIMIT 1") + suspend fun getSchedule(oid: Int): ScheduleUnitDB? + + @Query("SELECT * FROM scheduleUnitDB WHERE date = :date ORDER BY `begin`") + suspend fun getSchedule(date: String): List + + @Query("SELECT * FROM scheduleUnitDB WHERE date = :date ORDER BY `begin`") + fun getScheduleFlow(date: String): Flow> + + @Insert(onConflict = OnConflictStrategy.REPLACE) + suspend fun insert(units: List) + + @Delete + suspend fun delete(unit: ScheduleUnitDB) + + @Query("DELETE FROM scheduleUnitDB WHERE date = :date") + suspend fun deleteByDate(date: String) + + @Query("SELECT * FROM scheduleUnitDB WHERE date = :date ORDER BY `begin`") + fun observe(date: String): Flow> + + @Query("SELECT * FROM scheduleUnitDB") + suspend fun getAll(): List +} \ No newline at end of file diff --git a/app/src/main/java/ru/sweetbread/unn/core/db/dao/UserDao.kt b/app/src/main/java/ru/sweetbread/unn/core/db/dao/UserDao.kt new file mode 100644 index 0000000..54c8992 --- /dev/null +++ b/app/src/main/java/ru/sweetbread/unn/core/db/dao/UserDao.kt @@ -0,0 +1,21 @@ +// Copyright (c) 2026 Gleb Zaharov. License: GPLv3 (see LICENSE). + +package ru.sweetbread.unn.core.db.dao + +import androidx.room.Dao +import androidx.room.Delete +import androidx.room.Insert +import androidx.room.Query +import ru.sweetbread.unn.core.db.entity.UserDB + +@Dao +interface UserDao { + @Query("SELECT * FROM userDB WHERE userId = :userId LIMIT 1") + suspend fun get(userId: Int): UserDB? + + @Insert + suspend fun insert(user: UserDB) + + @Delete + fun delete(user: UserDB) +} \ No newline at end of file diff --git a/app/src/main/java/ru/sweetbread/unn/core/db/entity/Auditorium.kt b/app/src/main/java/ru/sweetbread/unn/core/db/entity/Auditorium.kt new file mode 100644 index 0000000..439a98a --- /dev/null +++ b/app/src/main/java/ru/sweetbread/unn/core/db/entity/Auditorium.kt @@ -0,0 +1,51 @@ +// Copyright (c) 2026 Gleb Zaharov. License: GPLv3 (see LICENSE). + +package ru.sweetbread.unn.core.db.entity + +import androidx.room.ColumnInfo +import androidx.room.Entity +import androidx.room.PrimaryKey +import androidx.room.withTransaction +import ru.sweetbread.unn.api.Auditorium +import ru.sweetbread.unn.core.db.AppDatabase +import java.time.LocalDateTime +import java.time.format.DateTimeFormatter + +@Entity +data class AuditoriumDB( + @PrimaryKey val oid: Int, + @ColumnInfo val name: String, + @ColumnInfo val floor: Int?, + @ColumnInfo val buildingOid: Int, + @ColumnInfo val updatedAt: String +) + + +suspend fun AuditoriumDB.toModel(db: AppDatabase): Auditorium? { + return Auditorium( + name, + oid, + floor ?: 0, + db.buildingDao().get(buildingOid)?.toModel() ?: return null + ) +} + +fun Auditorium.toEntity() = AuditoriumDB( + oid, + name, + floor, + building.oid, + LocalDateTime.now().format(DateTimeFormatter.ISO_DATE_TIME) +) + +suspend fun cacheAuditorium(db: AppDatabase, auditoriums: List) { + db.withTransaction { + db.buildingDao().insert( + auditoriums.map { it.building }.map { it.toEntity() } + ) + + db.auditoriumDao().insert( + auditoriums.map { it.toEntity() } + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/ru/sweetbread/unn/core/db/entity/Building.kt b/app/src/main/java/ru/sweetbread/unn/core/db/entity/Building.kt new file mode 100644 index 0000000..b93cb1b --- /dev/null +++ b/app/src/main/java/ru/sweetbread/unn/core/db/entity/Building.kt @@ -0,0 +1,21 @@ +// Copyright (c) 2026 Gleb Zaharov. License: GPLv3 (see LICENSE). + +package ru.sweetbread.unn.core.db.entity + +import androidx.room.ColumnInfo +import androidx.room.Entity +import androidx.room.PrimaryKey +import ru.sweetbread.unn.api.Building +import java.time.LocalDateTime +import java.time.format.DateTimeFormatter + +@Entity +data class BuildingDB( + @PrimaryKey val oid: Int, + @ColumnInfo val name: String, + @ColumnInfo val gid: Int, + @ColumnInfo val updatedAt: String +) + +fun BuildingDB.toModel() = Building(name, gid, oid) +fun Building.toEntity() = BuildingDB(oid, name, gid, LocalDateTime.now().format(DateTimeFormatter.ISO_DATE_TIME)) \ No newline at end of file diff --git a/app/src/main/java/ru/sweetbread/unn/core/db/entity/Discipline.kt b/app/src/main/java/ru/sweetbread/unn/core/db/entity/Discipline.kt new file mode 100644 index 0000000..2b15184 --- /dev/null +++ b/app/src/main/java/ru/sweetbread/unn/core/db/entity/Discipline.kt @@ -0,0 +1,22 @@ +// Copyright (c) 2026 Gleb Zaharov. License: GPLv3 (see LICENSE). + +package ru.sweetbread.unn.core.db.entity + +import androidx.room.ColumnInfo +import androidx.room.Entity +import androidx.room.PrimaryKey +import ru.sweetbread.unn.api.Discipline +import java.time.LocalDateTime +import java.time.format.DateTimeFormatter + +@Entity +data class DisciplineDB( + @PrimaryKey val oid: Int, + @ColumnInfo val name: String, + @ColumnInfo val type: Int, + @ColumnInfo val updatedAt: String +) + +fun DisciplineDB.toModel() = Discipline(name, oid, type) +fun Discipline.toEntity() = DisciplineDB(oid, name, type, LocalDateTime.now().format( + DateTimeFormatter.ISO_DATE_TIME)) \ No newline at end of file diff --git a/app/src/main/java/ru/sweetbread/unn/core/db/entity/KindOfWork.kt b/app/src/main/java/ru/sweetbread/unn/core/db/entity/KindOfWork.kt new file mode 100644 index 0000000..3ebd51e --- /dev/null +++ b/app/src/main/java/ru/sweetbread/unn/core/db/entity/KindOfWork.kt @@ -0,0 +1,28 @@ +// Copyright (c) 2026 Gleb Zaharov. License: GPLv3 (see LICENSE). + +package ru.sweetbread.unn.core.db.entity + +import androidx.room.ColumnInfo +import androidx.room.Entity +import androidx.room.PrimaryKey +import ru.sweetbread.unn.api.KindOfWork +import java.time.LocalDateTime +import java.time.format.DateTimeFormatter + +@Entity +data class KindOfWorkDB( + @PrimaryKey val oid: Int, + @ColumnInfo val name: String, + @ColumnInfo val uid: String, + @ColumnInfo val complexity: Int, + @ColumnInfo val updatedAt: String +) + +fun KindOfWorkDB.toModel() = KindOfWork(name, oid, uid, complexity) +fun KindOfWork.toEntity() = KindOfWorkDB( + oid, + name, + uid, + complexity, + LocalDateTime.now().format(DateTimeFormatter.ISO_DATE_TIME) +) \ No newline at end of file diff --git a/app/src/main/java/ru/sweetbread/unn/core/db/entity/Lecturer.kt b/app/src/main/java/ru/sweetbread/unn/core/db/entity/Lecturer.kt new file mode 100644 index 0000000..55495dc --- /dev/null +++ b/app/src/main/java/ru/sweetbread/unn/core/db/entity/Lecturer.kt @@ -0,0 +1,31 @@ +// Copyright (c) 2026 Gleb Zaharov. License: GPLv3 (see LICENSE). + +package ru.sweetbread.unn.core.db.entity + +import androidx.room.ColumnInfo +import androidx.room.Entity +import androidx.room.PrimaryKey +import ru.sweetbread.unn.api.Lecturer +import ru.sweetbread.unn.api.LecturerRank +import java.time.LocalDateTime +import java.time.format.DateTimeFormatter + +@Entity +data class LecturerDB( + @PrimaryKey val unnId: Int, + @ColumnInfo val name: String, + @ColumnInfo val rank: LecturerRank, + @ColumnInfo val email: String, + @ColumnInfo val uid: String, + @ColumnInfo val updatedAt: String +) + +fun LecturerDB.toModel() = Lecturer(name, rank, email, unnId, uid) +fun Lecturer.toEntity() = LecturerDB( + unnId, + name, + rank, + email, + uid, + LocalDateTime.now().format(DateTimeFormatter.ISO_DATE_TIME) +) \ No newline at end of file diff --git a/app/src/main/java/ru/sweetbread/unn/core/db/entity/News.kt b/app/src/main/java/ru/sweetbread/unn/core/db/entity/News.kt index 782367f..3bafd97 100644 --- a/app/src/main/java/ru/sweetbread/unn/core/db/entity/News.kt +++ b/app/src/main/java/ru/sweetbread/unn/core/db/entity/News.kt @@ -18,6 +18,7 @@ data class NewsDB( @ColumnInfo val authorId: Int ) + suspend fun NewsDB.toModel(userRepo: UserRepository): News = News( id, LocalDateTime.parse(publishedAt, DateTimeFormatter.ISO_DATE_TIME), diff --git a/app/src/main/java/ru/sweetbread/unn/core/db/entity/ScheduleUnit.kt b/app/src/main/java/ru/sweetbread/unn/core/db/entity/ScheduleUnit.kt new file mode 100644 index 0000000..b9ef774 --- /dev/null +++ b/app/src/main/java/ru/sweetbread/unn/core/db/entity/ScheduleUnit.kt @@ -0,0 +1,70 @@ +// Copyright (c) 2026 Gleb Zaharov. License: GPLv3 (see LICENSE). + +package ru.sweetbread.unn.core.db.entity + +import androidx.room.ColumnInfo +import androidx.room.Entity +import androidx.room.PrimaryKey +import androidx.room.withTransaction +import ru.sweetbread.unn.api.ScheduleUnit +import ru.sweetbread.unn.core.db.AppDatabase +import java.time.LocalDate +import java.time.LocalDateTime +import java.time.LocalTime +import java.time.format.DateTimeFormatter + +@Entity +data class ScheduleUnitDB( + @PrimaryKey val oid: Int, + @ColumnInfo val date: String, + @ColumnInfo val stream: String, + @ColumnInfo val begin: String, + @ColumnInfo val end: String, + + @ColumnInfo val auditoriumOid: Int, + @ColumnInfo val disciplineOid: Int, + @ColumnInfo val kindOfWorkOid: Int, + @ColumnInfo val lecturersId: String, + + @ColumnInfo val updatedAt: String +) + + +suspend fun ScheduleUnitDB.toModel(db: AppDatabase): ScheduleUnit? { + return ScheduleUnit( + oid, + db.auditoriumDao().get(auditoriumOid)?.toModel(db) ?: return null, + LocalDate.parse(date, DateTimeFormatter.ISO_DATE), + db.disciplineDao().get(disciplineOid)?.toModel() ?: return null, + db.kindOfWorkDao().get(kindOfWorkOid)?.toModel() ?: return null, + lecturersId.split(",").map { db.lecturerDao().get(it.toInt())?.toModel() ?: return null }, + stream, + LocalTime.parse(begin, DateTimeFormatter.ISO_TIME), + LocalTime.parse(end, DateTimeFormatter.ISO_TIME), + LocalDateTime.parse(updatedAt, DateTimeFormatter.ISO_DATE_TIME), + ) +} + +fun ScheduleUnit.toEntity() = ScheduleUnitDB( + oid, + date.format(DateTimeFormatter.ISO_DATE), + stream, + begin.format(DateTimeFormatter.ISO_TIME), + end.format(DateTimeFormatter.ISO_TIME), + auditorium.oid, + discipline.oid, + kindOfWork.oid, + lecturers.map { it.unnId }.joinToString(","), + LocalDateTime.now().format(DateTimeFormatter.ISO_DATE_TIME) +) + + +suspend fun cacheSchedule(db: AppDatabase, units: List) { + db.withTransaction { + cacheAuditorium(db, units.map { it.auditorium }) + db.disciplineDao().insert(units.map { it.discipline.toEntity() }) + db.kindOfWorkDao().insert(units.map { it.kindOfWork.toEntity() }) + db.lecturerDao().insert(units.flatMap { it.lecturers }.map { it.toEntity() }) + db.scheduleDao().insert(units.map { it.toEntity() }) + } +} \ No newline at end of file diff --git a/app/src/main/java/ru/sweetbread/unn/core/db/entity/UserDB.kt b/app/src/main/java/ru/sweetbread/unn/core/db/entity/User.kt similarity index 98% rename from app/src/main/java/ru/sweetbread/unn/core/db/entity/UserDB.kt rename to app/src/main/java/ru/sweetbread/unn/core/db/entity/User.kt index 53fa1a0..5ac5dbd 100644 --- a/app/src/main/java/ru/sweetbread/unn/core/db/entity/UserDB.kt +++ b/app/src/main/java/ru/sweetbread/unn/core/db/entity/User.kt @@ -29,6 +29,7 @@ data class UserDB( @ColumnInfo val updatedAt: String ) + fun User.toEntity(): UserDB = UserDB( userId, if (this.instanceOf(Student::class)) (this as Student).uns else null, @@ -45,7 +46,7 @@ fun User.toEntity(): UserDB = UserDB( ) fun UserDB.toModel(): User { - var user = User( + val user = User( userId, type, email, diff --git a/app/src/main/java/ru/sweetbread/unn/db/Schedule.kt b/app/src/main/java/ru/sweetbread/unn/db/Schedule.kt deleted file mode 100644 index 8085678..0000000 --- a/app/src/main/java/ru/sweetbread/unn/db/Schedule.kt +++ /dev/null @@ -1,269 +0,0 @@ -// Copyright (c) 2026 Gleb Zaharov. License: GPLv3 (see LICENSE). - -package ru.sweetbread.unn.db - -import androidx.room.ColumnInfo -import androidx.room.Dao -import androidx.room.Delete -import androidx.room.Entity -import androidx.room.Insert -import androidx.room.OnConflictStrategy -import androidx.room.PrimaryKey -import androidx.room.Query -import androidx.room.withTransaction -import kotlinx.coroutines.flow.Flow -import ru.sweetbread.unn.api.Auditorium -import ru.sweetbread.unn.api.Building -import ru.sweetbread.unn.api.Discipline -import ru.sweetbread.unn.api.KindOfWork -import ru.sweetbread.unn.api.Lecturer -import ru.sweetbread.unn.api.LecturerRank -import ru.sweetbread.unn.api.ScheduleUnit -import java.time.LocalDate -import java.time.LocalDateTime -import java.time.LocalTime -import java.time.format.DateTimeFormatter - -@Entity -data class BuildingDB( - @PrimaryKey val oid: Int, - @ColumnInfo val name: String, - @ColumnInfo val gid: Int, - @ColumnInfo val updatedAt: String -) - -@Dao -interface BuildingDao { - @Query("SELECT * FROM buildingdb WHERE oid = :oid LIMIT 1") - suspend fun get(oid: Int): BuildingDB? - - @Insert(onConflict = OnConflictStrategy.REPLACE) - suspend fun insert(buildings: List) - - @Delete - fun delete(building: BuildingDB) -} - -fun BuildingDB.toModel() = Building(name, gid, oid) -fun Building.toEntity() = BuildingDB(oid, name, gid, LocalDateTime.now().format(DateTimeFormatter.ISO_DATE_TIME)) - - -@Entity -data class AuditoriumDB( - @PrimaryKey val oid: Int, - @ColumnInfo val name: String, - @ColumnInfo val floor: Int?, - @ColumnInfo val buildingOid: Int, - @ColumnInfo val updatedAt: String -) - -@Dao -interface AuditoriumDao { - @Query("SELECT * FROM auditoriumdb WHERE oid = :oid LIMIT 1") - suspend fun get(oid: Int): AuditoriumDB? - - @Insert(onConflict = OnConflictStrategy.REPLACE) - suspend fun insert(auditoriums: List) - - @Delete - fun delete(auditorium: AuditoriumDB) -} - -suspend fun AuditoriumDB.toModel(db: AppDatabase): Auditorium? { - return Auditorium( - name, - oid, - floor ?: 0, - db.buildingDao().get(buildingOid)?.toModel() ?: return null - ) -} -fun Auditorium.toEntity() = AuditoriumDB( - oid, - name, - floor, - building.oid, - LocalDateTime.now().format(DateTimeFormatter.ISO_DATE_TIME) -) - -suspend fun cacheAuditorium(db: AppDatabase, auditoriums: List) { - db.withTransaction { - db.buildingDao().insert( - auditoriums.map { it.building }.map { it.toEntity() } - ) - - db.auditoriumDao().insert( - auditoriums.map { it.toEntity() } - ) - } -} - -@Entity -data class DisciplineDB( - @PrimaryKey val oid: Int, - @ColumnInfo val name: String, - @ColumnInfo val type: Int, - @ColumnInfo val updatedAt: String -) - -@Dao -interface DisciplineDao { - @Query("SELECT * FROM disciplinedb WHERE oid = :oid LIMIT 1") - suspend fun get(oid: Int): DisciplineDB? - - @Insert(onConflict = OnConflictStrategy.REPLACE) - suspend fun insert(disciplines: List) - - @Delete - fun delete(discipline: DisciplineDB) -} - -fun DisciplineDB.toModel() = Discipline(name, oid, type) -fun Discipline.toEntity() = DisciplineDB(oid, name, type, LocalDateTime.now().format(DateTimeFormatter.ISO_DATE_TIME)) - - -@Entity -data class KindOfWorkDB( - @PrimaryKey val oid: Int, - @ColumnInfo val name: String, - @ColumnInfo val uid: String, - @ColumnInfo val complexity: Int, - @ColumnInfo val updatedAt: String -) - -@Dao -interface KindOfWorkDao { - @Query("SELECT * FROM kindofworkdb WHERE oid = :oid LIMIT 1") - suspend fun get(oid: Int): KindOfWorkDB? - - @Insert(onConflict = OnConflictStrategy.REPLACE) - suspend fun insert(kindOfWork: List) - - @Delete - fun delete(kindOfWork: KindOfWorkDB) -} - -fun KindOfWorkDB.toModel() = KindOfWork(name, oid, uid, complexity) -fun KindOfWork.toEntity() = KindOfWorkDB( - oid, - name, - uid, - complexity, - LocalDateTime.now().format(DateTimeFormatter.ISO_DATE_TIME) -) - - -@Entity -data class LecturerDB( - @PrimaryKey val unnId: Int, - @ColumnInfo val name: String, - @ColumnInfo val rank: LecturerRank, - @ColumnInfo val email: String, - @ColumnInfo val uid: String, - @ColumnInfo val updatedAt: String -) - -@Dao -interface LecturerDao { - @Query("SELECT * FROM lecturerdb WHERE unnId = :unnId LIMIT 1") - suspend fun get(unnId: Int): LecturerDB? - - @Insert(onConflict = OnConflictStrategy.REPLACE) - suspend fun insert(lecturers: List) - - @Delete - fun delete(lecturer: LecturerDB) -} - -fun LecturerDB.toModel() = Lecturer(name, rank, email, unnId, uid) -fun Lecturer.toEntity() = LecturerDB( - unnId, - name, - rank, - email, - uid, - LocalDateTime.now().format(DateTimeFormatter.ISO_DATE_TIME) -) - - -@Entity -data class ScheduleUnitDB( - @PrimaryKey val oid: Int, - @ColumnInfo val date: String, - @ColumnInfo val stream: String, - @ColumnInfo val begin: String, - @ColumnInfo val end: String, - - @ColumnInfo val auditoriumOid: Int, - @ColumnInfo val disciplineOid: Int, - @ColumnInfo val kindOfWorkOid: Int, - @ColumnInfo val lecturersId: String, - - @ColumnInfo val updatedAt: String -) -@Dao -interface ScheduleItemDao { - @Query("SELECT * FROM scheduleUnitDB WHERE oid = :oid LIMIT 1") - suspend fun getSchedule(oid: Int): ScheduleUnitDB? - - @Query("SELECT * FROM scheduleUnitDB WHERE date = :date ORDER BY `begin`") - suspend fun getSchedule(date: String): List - - @Query("SELECT * FROM scheduleUnitDB WHERE date = :date ORDER BY `begin`") - fun getScheduleFlow(date: String): Flow> - - @Insert(onConflict = OnConflictStrategy.REPLACE) - suspend fun insert(units: List) - - @Delete - suspend fun delete(unit: ScheduleUnitDB) - - @Query("DELETE FROM scheduleUnitDB WHERE date = :date") - suspend fun deleteByDate(date: String) - - @Query("SELECT * FROM scheduleUnitDB WHERE date = :date ORDER BY `begin`") - fun observe(date: String): Flow> - - @Query("SELECT * FROM scheduleUnitDB") - suspend fun getAll(): List -} - -suspend fun ScheduleUnitDB.toModel(db: AppDatabase): ScheduleUnit? { - return ScheduleUnit( - oid, - db.auditoriumDao().get(auditoriumOid)?.toModel(db) ?: return null, - LocalDate.parse(date, DateTimeFormatter.ISO_DATE), - db.disciplineDao().get(disciplineOid)?.toModel() ?: return null, - db.kindOfWorkDao().get(kindOfWorkOid)?.toModel() ?: return null, - lecturersId.split(",").map { db.lecturerDao().get(it.toInt())?.toModel() ?: return null }, - stream, - LocalTime.parse(begin, DateTimeFormatter.ISO_TIME), - LocalTime.parse(end, DateTimeFormatter.ISO_TIME), - LocalDateTime.parse(updatedAt, DateTimeFormatter.ISO_DATE_TIME), - ) -} -fun ScheduleUnit.toEntity() = ScheduleUnitDB( - oid, - date.format(DateTimeFormatter.ISO_DATE), - stream, - begin.format(DateTimeFormatter.ISO_TIME), - end.format(DateTimeFormatter.ISO_TIME), - auditorium.oid, - discipline.oid, - kindOfWork.oid, - lecturers.map { it.unnId }.joinToString(","), - LocalDateTime.now().format(DateTimeFormatter.ISO_DATE_TIME) -) - -suspend fun cacheSchedule(db: AppDatabase, units: List) { - db.withTransaction { - cacheAuditorium(db, units.map { it.auditorium }) - db.disciplineDao().insert(units.map { it.discipline.toEntity() }) - db.kindOfWorkDao().insert(units.map { it.kindOfWork.toEntity() }) - db.lecturerDao().insert(units.flatMap { it.lecturers }.map { it.toEntity() }) - db.scheduleDao().insert(units.map { it.toEntity() }) - } -} - -//fun loadSchedule(db: AppDatabase, date: LocalDate): List = -// db.scheduleDao().getSchedule(date.format(DateTimeFormatter.ISO_DATE)) -// .mapNotNull { it.toModel(db) } diff --git a/app/src/main/java/ru/sweetbread/unn/db/UserDB.kt b/app/src/main/java/ru/sweetbread/unn/db/UserDB.kt deleted file mode 100644 index 2335664..0000000 --- a/app/src/main/java/ru/sweetbread/unn/db/UserDB.kt +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright (c) 2026 Gleb Zaharov. License: GPLv3 (see LICENSE). - -package ru.sweetbread.unn.db - -import androidx.room.Dao -import androidx.room.Delete -import androidx.room.Insert -import androidx.room.Query -import ru.sweetbread.unn.core.db.entity.UserDB - -@Dao -interface UserDao { - @Query("SELECT * FROM userDB WHERE userId = :userId LIMIT 1") - suspend fun get(userId: Int): UserDB? - - @Insert - suspend fun insert(user: UserDB) - - @Delete - fun delete(user: UserDB) -} - - -//fun cacheUser(user: User) { -// try { -// cacheDb.userDao().insert( -// UserDB( -// user.userId, -// user.unnId, -// user.type, -// user.email, -// user.nameRu, -// user.nameEn, -// user.isMale, -// user.birthday.format(DateTimeFormatter.ISO_LOCAL_DATE), -// user.avatar.original, -// user.avatar.thumbnail, -// user.avatar.small, -// LocalDateTime.now().plusDays(1).format(DateTimeFormatter.ISO_LOCAL_DATE_TIME) -// ) -// ) -// } catch (_: android.database.sqlite.SQLiteConstraintException) { -// } -//} -// -//fun loadUserByBitrixId(bitrixId: Int): User? { -// val user = cacheDb.userDao().getUserById(bitrixId) -// Log.d("UserDB", user?.nameEn ?: "None") -// if (user == null) return null -// if (LocalDateTime.parse( -// user.expiredAt, -// DateTimeFormatter.ISO_LOCAL_DATE_TIME -// ) < LocalDateTime.now() -// ) { -// cacheDb.userDao().delete(user) -// return null -// } else { -// return User( -// user.unnId, -// user.userId, -// user.type, -// user.email, -// user.nameRu, -// user.nameEn, -// user.isMale, -// LocalDate.parse(user.birthday, DateTimeFormatter.ISO_LOCAL_DATE), -// AvatarSet( -// user.origAvatar, -// user.thumbAvatar, -// user.smallAvatar -// ) -// ) -// } -//} \ No newline at end of file diff --git a/app/src/main/java/ru/sweetbread/unn/feature/news/NewsRemoteMediator.kt b/app/src/main/java/ru/sweetbread/unn/feature/news/NewsRemoteMediator.kt index 59a8ad8..4b0d5c1 100644 --- a/app/src/main/java/ru/sweetbread/unn/feature/news/NewsRemoteMediator.kt +++ b/app/src/main/java/ru/sweetbread/unn/feature/news/NewsRemoteMediator.kt @@ -11,10 +11,10 @@ import androidx.paging.PagingState import androidx.paging.RemoteMediator import androidx.room.withTransaction import kotlinx.io.IOException +import ru.sweetbread.unn.core.db.AppDatabase import ru.sweetbread.unn.core.db.entity.NewsDB import ru.sweetbread.unn.core.db.entity.toEntity import ru.sweetbread.unn.core.network.PortalApi -import ru.sweetbread.unn.db.AppDatabase import ru.sweetbread.unn.feature.profile.UserRepository import ru.sweetbread.unn.model.News diff --git a/app/src/main/java/ru/sweetbread/unn/feature/news/NewsRepository.kt b/app/src/main/java/ru/sweetbread/unn/feature/news/NewsRepository.kt index cfc4545..b1c9f22 100644 --- a/app/src/main/java/ru/sweetbread/unn/feature/news/NewsRepository.kt +++ b/app/src/main/java/ru/sweetbread/unn/feature/news/NewsRepository.kt @@ -10,9 +10,9 @@ import androidx.paging.map import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map import ru.sweetbread.unn.core.SessionManager +import ru.sweetbread.unn.core.db.AppDatabase import ru.sweetbread.unn.core.db.entity.toModel import ru.sweetbread.unn.core.network.PortalApi -import ru.sweetbread.unn.db.AppDatabase import ru.sweetbread.unn.feature.profile.UserRepository import ru.sweetbread.unn.model.News diff --git a/app/src/main/java/ru/sweetbread/unn/feature/profile/UserRepository.kt b/app/src/main/java/ru/sweetbread/unn/feature/profile/UserRepository.kt index 7cff4c7..2603b1e 100644 --- a/app/src/main/java/ru/sweetbread/unn/feature/profile/UserRepository.kt +++ b/app/src/main/java/ru/sweetbread/unn/feature/profile/UserRepository.kt @@ -3,10 +3,10 @@ package ru.sweetbread.unn.feature.profile import android.util.Log +import ru.sweetbread.unn.core.db.AppDatabase import ru.sweetbread.unn.core.db.entity.toEntity import ru.sweetbread.unn.core.db.entity.toModel import ru.sweetbread.unn.core.network.PortalApi -import ru.sweetbread.unn.db.AppDatabase import ru.sweetbread.unn.model.User class UserRepository ( diff --git a/app/src/main/java/ru/sweetbread/unn/feature/schedule/ScheduleRepository.kt b/app/src/main/java/ru/sweetbread/unn/feature/schedule/ScheduleRepository.kt index dc951c3..5113e54 100644 --- a/app/src/main/java/ru/sweetbread/unn/feature/schedule/ScheduleRepository.kt +++ b/app/src/main/java/ru/sweetbread/unn/feature/schedule/ScheduleRepository.kt @@ -7,10 +7,10 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map import ru.sweetbread.unn.api.ScheduleUnit import ru.sweetbread.unn.core.SessionManager +import ru.sweetbread.unn.core.db.AppDatabase +import ru.sweetbread.unn.core.db.entity.cacheSchedule +import ru.sweetbread.unn.core.db.entity.toModel import ru.sweetbread.unn.core.network.PortalApi -import ru.sweetbread.unn.db.AppDatabase -import ru.sweetbread.unn.db.cacheSchedule -import ru.sweetbread.unn.db.toModel import java.time.LocalDate import java.time.LocalDateTime import java.time.format.DateTimeFormatter