[DB] Refactor database and entities.

This commit is contained in:
Kuba Szczodrzyński 2020-04-29 15:14:45 +02:00
parent 13a3f66db3
commit 3f61ab8299
144 changed files with 1788 additions and 1492 deletions

View File

@ -66,6 +66,7 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
val timetableManager by lazy { TimetableManager(this) }
val eventManager by lazy { EventManager(this) }
val permissionManager by lazy { PermissionManager(this) }
val attendanceManager by lazy { AttendanceManager(this) }
val db
get() = App.db

View File

@ -68,6 +68,9 @@ object Regexes {
}
val MOBIDZIENNIK_ATTENDANCE_TYPES by lazy {
"""Legenda:.+?normal;">(.+?)</span>""".toRegex(DOT_MATCHES_ALL)
}
val MOBIDZIENNIK_ATTENDANCE_TABLE by lazy {
"""<table .+?id="obecnosci_tabela">(.+?)</table>""".toRegex(DOT_MATCHES_ALL)
}

View File

@ -45,24 +45,25 @@ class EdudziennikWebAnnouncements(override val data: DataEdudziennik,
val addedDate = Date.fromIsoHm(dateString)
val announcementObject = Announcement(
profileId,
id,
subject,
null,
startDate,
null,
teacher.id,
longId
)
profileId = profileId,
id = id,
subject = subject,
text = null,
startDate = startDate,
endDate = null,
teacherId = teacher.id,
addedDate = addedDate
).also {
it.idString = longId
}
data.announcementIgnoreList.add(announcementObject)
data.announcementList.add(announcementObject)
data.metadataList.add(Metadata(
profileId,
Metadata.TYPE_ANNOUNCEMENT,
id,
profile.empty,
profile.empty,
addedDate
profile.empty
))
}
}

View File

@ -39,12 +39,12 @@ class EdudziennikWebAttendance(override val data: DataEdudziennik,
val attendanceTypes = EDUDZIENNIK_ATTENDANCE_TYPES.find(text)?.get(1)?.split(',')?.map {
val type = EDUDZIENNIK_ATTENDANCE_TYPE.find(it.trim())
val symbol = type?.get(1)?.trim()
val name = type?.get(2)?.trim()
val symbol = type?.get(1)?.trim() ?: "?"
val name = type?.get(2)?.trim() ?: "nieznany rodzaj"
return@map Triple(
symbol,
name,
when (name?.toLowerCase(Locale.ROOT)) {
when (name.toLowerCase(Locale.ROOT)) {
"obecność" -> Attendance.TYPE_PRESENT
"nieobecność" -> Attendance.TYPE_ABSENT
"spóźnienie" -> Attendance.TYPE_BELATED
@ -52,7 +52,7 @@ class EdudziennikWebAttendance(override val data: DataEdudziennik,
"dzień wolny" -> Attendance.TYPE_DAY_FREE
"brak zajęć" -> Attendance.TYPE_DAY_FREE
"oddelegowany" -> Attendance.TYPE_RELEASED
else -> Attendance.TYPE_CUSTOM
else -> Attendance.TYPE_UNKNOWN
}
)
} ?: emptyList()
@ -62,38 +62,42 @@ class EdudziennikWebAttendance(override val data: DataEdudziennik,
val lessonNumber = attendanceElement[2].toInt()
val attendanceSymbol = attendanceElement[3]
val lessons = data.app.db.timetableDao().getForDateNow(profileId, date)
val lessons = data.app.db.timetableDao().getAllForDateNow(profileId, date)
val lesson = lessons.firstOrNull { it.lessonNumber == lessonNumber }
val id = "${date.stringY_m_d}:$lessonNumber:$attendanceSymbol".crc32()
val (_, name, type) = attendanceTypes.firstOrNull { (symbol, _, _) -> symbol == attendanceSymbol }
val (typeSymbol, typeName, baseType) = attendanceTypes.firstOrNull { (symbol, _, _) -> symbol == attendanceSymbol }
?: return@forEach
val startTime = data.lessonRanges.singleOrNull { it.lessonNumber == lessonNumber }?.startTime
?: return@forEach
val attendanceObject = Attendance(
profileId,
id,
lesson?.displayTeacherId ?: -1,
lesson?.displaySubjectId ?: -1,
profile.currentSemester,
name,
date,
lesson?.displayStartTime ?: startTime,
type
)
profileId = profileId,
id = id,
baseType = baseType,
typeName = typeName,
typeShort = data.app.attendanceManager.getTypeShort(baseType),
typeSymbol = typeSymbol,
typeColor = null,
date = date,
startTime = lesson?.displayStartTime ?: startTime,
semester = profile.currentSemester,
teacherId = lesson?.displayTeacherId ?: -1,
subjectId = lesson?.displaySubjectId ?: -1
).also {
it.lessonNumber = lessonNumber
}
data.attendanceList.add(attendanceObject)
if(type != Attendance.TYPE_PRESENT) {
if (baseType != Attendance.TYPE_PRESENT) {
data.metadataList.add(Metadata(
profileId,
Metadata.TYPE_ATTENDANCE,
id,
profile.empty,
profile.empty,
System.currentTimeMillis()
profile.empty
))
}
}

View File

@ -57,8 +57,7 @@ class EdudziennikWebEvents(override val data: DataEdudziennik,
Metadata.TYPE_EVENT,
id,
profile.empty,
profile.empty,
System.currentTimeMillis()
profile.empty
))
}

View File

@ -46,7 +46,7 @@ class EdudziennikWebExams(override val data: DataEdudziennik,
if (dateString.isBlank()) return@forEach
val date = Date.fromY_m_d(dateString)
val lessons = data.app.db.timetableDao().getForDateNow(profileId, date)
val lessons = data.app.db.timetableDao().getAllForDateNow(profileId, date)
val startTime = lessons.firstOrNull { it.displaySubjectId == subject.id }?.displayStartTime
val eventTypeElement = examElement.child(3).child(0)
@ -74,8 +74,7 @@ class EdudziennikWebExams(override val data: DataEdudziennik,
Metadata.TYPE_EVENT,
id,
profile.empty,
profile.empty,
System.currentTimeMillis()
profile.empty
))
}

View File

@ -126,7 +126,8 @@ class EdudziennikWebGrades(override val data: DataEdudziennik,
comment = null,
semester = semester,
teacherId = teacher.id,
subjectId = subject.id
subjectId = subject.id,
addedDate = addedDate
)
data.gradeList.add(gradeObject)
@ -135,8 +136,7 @@ class EdudziennikWebGrades(override val data: DataEdudziennik,
Metadata.TYPE_GRADE,
id,
profile.empty,
profile.empty,
addedDate
profile.empty
))
}
@ -168,8 +168,7 @@ class EdudziennikWebGrades(override val data: DataEdudziennik,
Metadata.TYPE_GRADE,
proposedGradeObject.id,
profile.empty,
profile.empty,
System.currentTimeMillis()
profile.empty
))
}
@ -201,8 +200,7 @@ class EdudziennikWebGrades(override val data: DataEdudziennik,
Metadata.TYPE_GRADE,
finalGradeObject.id,
profile.empty,
profile.empty,
System.currentTimeMillis()
profile.empty
))
}
}

View File

@ -43,7 +43,7 @@ class EdudziennikWebHomework(override val data: DataEdudziennik,
val subjectName = subjectElement.text()
val subject = data.getSubject(subjectId, subjectName)
val lessons = data.app.db.timetableDao().getForDateNow(profileId, date)
val lessons = data.app.db.timetableDao().getAllForDateNow(profileId, date)
val startTime = lessons.firstOrNull { it.subjectId == subject.id }?.displayStartTime
val teacherName = homeworkElement.child(2).text()
@ -72,8 +72,7 @@ class EdudziennikWebHomework(override val data: DataEdudziennik,
Metadata.TYPE_HOMEWORK,
id,
profile.empty,
profile.empty,
System.currentTimeMillis()
profile.empty
))
}
}

View File

@ -24,9 +24,9 @@ class EdudziennikWebLuckyNumber(override val data: DataEdudziennik,
webGet(TAG, data.schoolEndpoint + "Lucky", xhr = true) { text ->
text.toIntOrNull()?.also { luckyNumber ->
val luckyNumberObject = LuckyNumber(
profileId,
Date.getToday(),
luckyNumber
profileId = profileId,
date = Date.getToday(),
number = luckyNumber
)
data.luckyNumberList.add(luckyNumberObject)
@ -35,8 +35,7 @@ class EdudziennikWebLuckyNumber(override val data: DataEdudziennik,
Metadata.TYPE_LUCKY_NUMBER,
luckyNumberObject.date.value.toLong(),
true,
profile.empty,
System.currentTimeMillis()
profile.empty
))
}

View File

@ -41,12 +41,15 @@ class EdudziennikWebNotes(override val data: DataEdudziennik,
val description = noteElement.child(3).text()
val noticeObject = Notice(
profileId,
id,
description,
profile.currentSemester,
Notice.TYPE_NEUTRAL,
teacher.id
profileId = profileId,
id = id,
type = Notice.TYPE_NEUTRAL,
semester = profile.currentSemester,
text = description,
category = null,
points = null,
teacherId = teacher.id,
addedDate = addedDate
)
data.noticeList.add(noticeObject)
@ -55,8 +58,7 @@ class EdudziennikWebNotes(override val data: DataEdudziennik,
Metadata.TYPE_NOTICE,
id,
profile.empty,
profile.empty,
addedDate
profile.empty
))
}

View File

@ -124,8 +124,7 @@ class EdudziennikWebTimetable(override val data: DataEdudziennik,
Metadata.TYPE_LESSON_CHANGE,
lessonObject.id,
seen,
seen,
System.currentTimeMillis()
seen
))
}
}

View File

@ -68,9 +68,9 @@ class IdziennikApiCurrentRegister(override val data: DataIdziennik,
val luckyNumberObject = LuckyNumber(
data.profileId,
luckyNumberDate,
luckyNumber
profileId = data.profileId,
date = luckyNumberDate,
number = luckyNumber
)
data.luckyNumberList.add(luckyNumberObject)
@ -80,8 +80,7 @@ class IdziennikApiCurrentRegister(override val data: DataIdziennik,
Metadata.TYPE_LUCKY_NUMBER,
luckyNumberObject.date.value.toLong(),
true,
data.profile?.empty ?: false,
System.currentTimeMillis()
data.profile?.empty ?: false
))
}

View File

@ -69,7 +69,8 @@ class IdziennikApiMessagesInbox(override val data: DataIdziennik,
type = if (jMessage.getBoolean("rekordUsuniety") == true) TYPE_DELETED else TYPE_RECEIVED,
subject = subject,
body = body,
senderId = rTeacher.id
senderId = rTeacher.id,
addedDate = sentDate
)
val messageRecipient = MessageRecipient(
@ -87,8 +88,7 @@ class IdziennikApiMessagesInbox(override val data: DataIdziennik,
Metadata.TYPE_MESSAGE,
message.id,
readDate > 0,
readDate > 0 || profile?.empty ?: false,
sentDate
readDate > 0 || profile?.empty ?: false
))
}

View File

@ -51,7 +51,8 @@ class IdziennikApiMessagesSent(override val data: DataIdziennik,
type = TYPE_SENT,
subject = subject,
body = body,
senderId = null
senderId = null,
addedDate = sentDate
)
for (recipientEl in jMessage.getAsJsonArray("odbiorcy")) {
@ -76,7 +77,7 @@ class IdziennikApiMessagesSent(override val data: DataIdziennik,
}
data.messageList.add(message)
data.metadataList.add(Metadata(profileId, Metadata.TYPE_MESSAGE, message.id, true, true, sentDate))
data.metadataList.add(Metadata(profileId, Metadata.TYPE_MESSAGE, message.id, true, true))
}
data.setSyncNext(ENDPOINT_IDZIENNIK_API_MESSAGES_SENT, DAY, DRAWER_ITEM_MESSAGES)

View File

@ -52,14 +52,14 @@ class IdziennikWebAnnouncements(override val data: DataIdziennik,
val startDate = jAnnouncement.getString("DataWydarzenia")?.replace("[^\\d]".toRegex(), "")?.toLongOrNull()?.let { Date.fromMillis(it) }
val announcementObject = Announcement(
profileId,
announcementId,
jAnnouncement.get("Temat").asString,
jAnnouncement.get("Tresc").asString,
startDate,
null,
rTeacher.id,
null
profileId = profileId,
id = announcementId,
subject = jAnnouncement.get("Temat").asString,
text = jAnnouncement.get("Tresc").asString,
startDate = startDate,
endDate = null,
teacherId = rTeacher.id,
addedDate = addedDate
)
data.announcementList.add(announcementObject)
data.metadataList.add(Metadata(
@ -67,8 +67,7 @@ class IdziennikWebAnnouncements(override val data: DataIdziennik,
Metadata.TYPE_ANNOUNCEMENT,
announcementObject.id,
profile?.empty ?: false,
profile?.empty ?: false,
addedDate
profile?.empty ?: false
))
}

View File

@ -12,10 +12,18 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.ENDPOINT_IDZIENNI
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.IdziennikWeb
import pl.szczodrzynski.edziennik.data.api.models.ApiError
import pl.szczodrzynski.edziennik.data.db.entity.Attendance
import pl.szczodrzynski.edziennik.data.db.entity.Attendance.*
import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_ABSENT
import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_ABSENT_EXCUSED
import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_BELATED
import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_PRESENT
import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_PRESENT_CUSTOM
import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_RELEASED
import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_UNKNOWN
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
import pl.szczodrzynski.edziennik.getInt
import pl.szczodrzynski.edziennik.getJsonObject
import pl.szczodrzynski.edziennik.getString
import pl.szczodrzynski.edziennik.utils.models.Date
import pl.szczodrzynski.edziennik.utils.models.Time
@ -51,71 +59,97 @@ class IdziennikWebAttendance(override val data: DataIdziennik,
for (jAttendanceEl in json.getAsJsonArray("Obecnosci")) {
val jAttendance = jAttendanceEl.asJsonObject
// jAttendance
val attendanceTypeIdziennik = jAttendance.get("TypObecnosci").asInt
if (attendanceTypeIdziennik == 5 || attendanceTypeIdziennik == 7)
continue
val attendanceDate = Date.fromY_m_d(jAttendance.get("Data").asString)
val attendanceTime = Time.fromH_m(jAttendance.get("OdDoGodziny").asString)
if (attendanceDate.combineWith(attendanceTime) > System.currentTimeMillis())
val type = jAttendance.get("TypObecnosci").asInt
// skip "zajęcia nie odbyły się" and "Ferie"
if (type == 5 || type == 7)
continue
val attendanceId = jAttendance.get("IdLesson").asString.crc16().toLong()
val date = Date.fromY_m_d(jAttendance.get("Data").asString)
val time = Time.fromH_m(jAttendance.get("OdDoGodziny").asString)
if (date.combineWith(time) > System.currentTimeMillis())
continue
val id = jAttendance.get("IdLesson").asString.crc16().toLong()
val rSubject = data.getSubject(jAttendance.get("Przedmiot").asString, jAttendance.get("IdPrzedmiot").asLong, "")
val rTeacher = data.getTeacherByFDotSpaceLast(jAttendance.get("PrzedmiotNauczyciel").asString)
var attendanceName = "obecność"
var attendanceType = Attendance.TYPE_CUSTOM
var baseType = TYPE_UNKNOWN
var typeName = "nieznany rodzaj"
var typeSymbol: String? = null
var typeColor: Long? = null
when (attendanceTypeIdziennik) {
1 /* nieobecność usprawiedliwiona */ -> {
attendanceName = "nieobecność usprawiedliwiona"
attendanceType = TYPE_ABSENT_EXCUSED
/* https://iuczniowie.progman.pl/idziennik/mod_panelRodzica/obecnosci/obecnosciUcznia_lmt637231494660000000.js */
/* https://iuczniowie.progman.pl/idziennik/mod_panelRodzica/obecnosci/obecnosci_lmt637231494660000000.css */
when (type) {
1 -> {
baseType = TYPE_ABSENT_EXCUSED
typeName = "nieobecność usprawiedliwiona"
typeColor = 0xffffe099
}
2 /* spóźnienie */ -> {
attendanceName = "spóźnienie"
attendanceType = TYPE_BELATED
2 -> {
baseType = TYPE_BELATED
typeName = "spóźnienie"
typeColor = 0xffffffaa
}
3 /* nieobecność nieusprawiedliwiona */ -> {
attendanceName = "nieobecność nieusprawiedliwiona"
attendanceType = TYPE_ABSENT
3 -> {
baseType = TYPE_ABSENT
typeName = "nieobecność nieusprawiedliwiona"
typeColor = 0xffffad99
}
4 /* zwolnienie */, 9 /* zwolniony / obecny */ -> {
attendanceType = TYPE_RELEASED
if (attendanceTypeIdziennik == 4)
attendanceName = "zwolnienie"
if (attendanceTypeIdziennik == 9)
attendanceName = "zwolnienie / obecność"
4, 9 -> {
baseType = TYPE_RELEASED
if (type == 4) {
typeName = "zwolnienie"
typeColor = 0xffa8beff
}
if (type == 9) {
typeName = "zwolniony / obecny"
typeSymbol = "zb"
typeColor = 0xffff69b4
}
}
0 /* obecny */, 8 /* Wycieczka */ -> {
attendanceType = TYPE_PRESENT
if (attendanceTypeIdziennik == 8)
attendanceName = "wycieczka"
8 -> {
baseType = TYPE_PRESENT_CUSTOM
typeName = "wycieczka"
typeSymbol = "w"
typeColor = null
}
0 -> {
baseType = TYPE_PRESENT
typeName = "obecny"
typeColor = 0xffccffcc
}
}
val semester = profile?.dateToSemester(attendanceDate) ?: 1
val semester = profile?.dateToSemester(date) ?: 1
val attendanceObject = Attendance(
profileId,
attendanceId,
rTeacher.id,
rSubject.id,
semester,
attendanceName,
attendanceDate,
attendanceTime,
attendanceType
)
profileId = profileId,
id = id,
baseType = baseType,
typeName = typeName,
typeShort = typeSymbol ?: data.app.attendanceManager.getTypeShort(baseType),
typeSymbol = typeSymbol ?: data.app.attendanceManager.getTypeShort(baseType),
typeColor = typeColor?.toInt(),
date = date,
startTime = time,
semester = semester,
teacherId = rTeacher.id,
subjectId = rSubject.id
).also {
it.lessonTopic = jAttendance.getString("PrzedmiotTemat")
it.lessonNumber = jAttendance.getInt("Godzina")
}
data.attendanceList.add(attendanceObject)
if (attendanceObject.type != TYPE_PRESENT) {
if (attendanceObject.baseType != TYPE_PRESENT) {
data.metadataList.add(Metadata(
profileId,
Metadata.TYPE_ATTENDANCE,
attendanceObject.id,
profile?.empty ?: false,
profile?.empty ?: false,
System.currentTimeMillis()
profile?.empty ?: false
))
}
}

View File

@ -68,7 +68,7 @@ class IdziennikWebExams(override val data: DataIdziennik,
val teacherId = data.getTeacherByLastFirst(teacherName).id
val topic = exam.getString("zakres")?.trim() ?: ""
val lessonList = data.db.timetableDao().getForDateNow(profileId, examDate)
val lessonList = data.db.timetableDao().getAllForDateNow(profileId, examDate)
val startTime = lessonList.firstOrNull { it.subjectId == subjectId }?.startTime
val eventType = when (exam.getString("rodzaj")?.toLowerCase(Locale.getDefault())) {
@ -98,8 +98,7 @@ class IdziennikWebExams(override val data: DataIdziennik,
Metadata.TYPE_EVENT,
eventObject.id,
profile?.empty ?: false,
profile?.empty ?: false,
System.currentTimeMillis()
profile?.empty ?: false
))
}

View File

@ -94,8 +94,7 @@ class IdziennikWebGetMessage(override val data: DataIdziennik,
Metadata.TYPE_MESSAGE,
message.id,
message.seen,
message.notified,
message.addedDate
message.notified
))
}

View File

@ -63,6 +63,8 @@ class IdziennikWebGrades(override val data: DataIdziennik,
colorInt = Color.parseColor("#$gradeColor")
}
val addedDate = grade.getString("Data_wystaw")?.let { Date.fromY_m_d(it).inMillis } ?: System.currentTimeMillis()
val gradeObject = Grade(
profileId = profileId,
id = id,
@ -76,7 +78,9 @@ class IdziennikWebGrades(override val data: DataIdziennik,
comment = null,
semester = semester,
teacherId = teacher.id,
subjectId = subject.id)
subjectId = subject.id,
addedDate = addedDate
)
when (grade.getInt("Typ")) {
0 -> {
@ -100,6 +104,8 @@ class IdziennikWebGrades(override val data: DataIdziennik,
colorInt = Color.parseColor("#$historyColor")
}
val addedDate = historyItem.getString("Data_wystaw")?.let { Date.fromY_m_d(it).inMillis } ?: System.currentTimeMillis()
val historyObject = Grade(
profileId = profileId,
id = gradeObject.id * -1,
@ -113,19 +119,18 @@ class IdziennikWebGrades(override val data: DataIdziennik,
comment = null,
semester = historyItem.getInt("Semestr") ?: 1,
teacherId = teacher.id,
subjectId = subject.id)
subjectId = subject.id,
addedDate = addedDate
)
historyObject.parentId = gradeObject.id
val addedDate = historyItem.getString("Data_wystaw")?.let { Date.fromY_m_d(it).inMillis } ?: System.currentTimeMillis()
data.gradeList.add(historyObject)
data.metadataList.add(Metadata(
profileId,
Metadata.TYPE_GRADE,
historyObject.id,
true,
true,
addedDate
true
))
}
// update the current grade's value with an average of all historical grades and itself
@ -147,8 +152,6 @@ class IdziennikWebGrades(override val data: DataIdziennik,
}
}
val addedDate = grade.getString("Data_wystaw")?.let { Date.fromY_m_d(it).inMillis } ?: System.currentTimeMillis()
data.gradeList.add(gradeObject)
data.metadataList.add(
Metadata(
@ -156,8 +159,7 @@ class IdziennikWebGrades(override val data: DataIdziennik,
Metadata.TYPE_GRADE,
id,
data.profile.empty,
data.profile.empty,
addedDate
data.profile.empty
))
}
}

View File

@ -57,7 +57,7 @@ class IdziennikWebHomework(override val data: DataIdziennik,
val subjectId = data.getSubject(subjectName, null, subjectName).id
val teacherName = homework.getString("usr") ?: return@forEach
val teacherId = data.getTeacherByLastFirst(teacherName).id
val lessonList = data.db.timetableDao().getForDateNow(profileId, eventDate)
val lessonList = data.db.timetableDao().getAllForDateNow(profileId, eventDate)
val startTime = lessonList.firstOrNull { it.subjectId == subjectId }?.displayStartTime
val topic = homework.getString("tytul")?.trim() ?: ""
@ -77,7 +77,8 @@ class IdziennikWebHomework(override val data: DataIdziennik,
type = Event.TYPE_HOMEWORK,
teacherId = teacherId,
subjectId = subjectId,
teamId = data.teamClass?.id ?: -1
teamId = data.teamClass?.id ?: -1,
addedDate = addedDate.inMillis
)
data.eventList.add(eventObject)
@ -86,8 +87,7 @@ class IdziennikWebHomework(override val data: DataIdziennik,
Metadata.TYPE_HOMEWORK,
eventObject.id,
seen,
seen,
addedDate.inMillis
seen
))
}

View File

@ -13,9 +13,12 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.IdziennikWeb
import pl.szczodrzynski.edziennik.data.api.models.ApiError
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.entity.Notice
import pl.szczodrzynski.edziennik.data.db.entity.Notice.*
import pl.szczodrzynski.edziennik.data.db.entity.Notice.Companion.TYPE_NEGATIVE
import pl.szczodrzynski.edziennik.data.db.entity.Notice.Companion.TYPE_NEUTRAL
import pl.szczodrzynski.edziennik.data.db.entity.Notice.Companion.TYPE_POSITIVE
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
import pl.szczodrzynski.edziennik.getJsonObject
import pl.szczodrzynski.edziennik.getString
import pl.szczodrzynski.edziennik.utils.models.Date
class IdziennikWebNotices(override val data: DataIdziennik,
@ -53,20 +56,24 @@ class IdziennikWebNotices(override val data: DataIdziennik,
}
val noticeObject = Notice(
profileId,
noticeId,
jNotice.get("Tresc").asString,
jNotice.get("Semestr").asInt,
nType,
rTeacher.id)
profileId = profileId,
id = noticeId,
type = nType,
semester = jNotice.get("Semestr").asInt,
text = jNotice.getString("Tresc") ?: "",
category = null,
points = null,
teacherId = rTeacher.id,
addedDate = addedDate.inMillis
)
data.noticeList.add(noticeObject)
data.metadataList.add(Metadata(
profileId,
Metadata.TYPE_NOTICE,
noticeObject.id,
profile?.empty ?: false,
profile?.empty ?: false,
addedDate.inMillis
profile?.empty ?: false
))
}

View File

@ -76,6 +76,11 @@ class IdziennikWebProposedGrades(override val data: DataIdziennik,
else -1
if (semester1Proposed != "") {
val addedDate = if (data.profile.empty)
data.profile.dateSemester1Start.inMillis
else
System.currentTimeMillis()
val gradeObject = Grade(
profileId = profileId,
id = semester1Id,
@ -89,26 +94,26 @@ class IdziennikWebProposedGrades(override val data: DataIdziennik,
comment = null,
semester = 1,
teacherId = -1,
subjectId = subjectObject.id
subjectId = subjectObject.id,
addedDate = addedDate
)
val addedDate = if (data.profile.empty)
data.profile.dateSemester1Start.inMillis
else
System.currentTimeMillis()
data.gradeList.add(gradeObject)
data.metadataList.add(Metadata(
profileId,
Metadata.TYPE_GRADE,
gradeObject.id,
profile.empty,
profile.empty,
addedDate
profile.empty
))
}
if (semester2Proposed != "") {
val addedDate = if (data.profile.empty)
data.profile.dateSemester2Start.inMillis
else
System.currentTimeMillis()
val gradeObject = Grade(
profileId = profileId,
id = semester2Id,
@ -122,22 +127,17 @@ class IdziennikWebProposedGrades(override val data: DataIdziennik,
comment = null,
semester = 2,
teacherId = -1,
subjectId = subjectObject.id
subjectId = subjectObject.id,
addedDate = addedDate
)
val addedDate = if (data.profile.empty)
data.profile.dateSemester2Start.inMillis
else
System.currentTimeMillis()
data.gradeList.add(gradeObject)
data.metadataList.add(Metadata(
profileId,
Metadata.TYPE_GRADE,
gradeObject.id,
profile.empty,
profile.empty,
addedDate
profile.empty
))
}
}

View File

@ -59,7 +59,7 @@ class IdziennikWebSendMessage(override val data: DataIdziennik,
IdziennikApiMessagesSent(data, null) {
val message = data.messageList.firstOrNull { it.type == Message.TYPE_SENT && it.subject == subject }
val metadata = data.metadataList.firstOrNull { it.thingType == Metadata.TYPE_MESSAGE && it.thingId == message?.id }
val event = MessageSentEvent(data.profileId, message, metadata?.addedDate)
val event = MessageSentEvent(data.profileId, message, message?.addedDate)
EventBus.getDefault().postSticky(event)
onSuccess()

View File

@ -165,8 +165,7 @@ class IdziennikWebTimetable(override val data: DataIdziennik,
Metadata.TYPE_LESSON_CHANGE,
lessonObject.id,
seen,
seen,
System.currentTimeMillis()
seen
))
}
}

View File

@ -74,9 +74,9 @@ class IdziennikLoginWeb(val data: DataIdziennik, val onSuccess: () -> Unit) {
Regexes.IDZIENNIK_WEB_LUCKY_NUMBER.find(text)?.also {
val number = it[1].toIntOrNull() ?: return@also
val luckyNumberObject = LuckyNumber(
data.profileId,
Date.getToday(),
number
profileId = data.profileId,
date = Date.getToday(),
number = number
)
data.luckyNumberList.add(luckyNumberObject)
@ -86,8 +86,7 @@ class IdziennikLoginWeb(val data: DataIdziennik, val onSuccess: () -> Unit) {
Metadata.TYPE_LUCKY_NUMBER,
luckyNumberObject.date.value.toLong(),
true,
profile.empty,
System.currentTimeMillis()
profile.empty
))
}
}

View File

@ -37,8 +37,7 @@ class LibrusApiAnnouncementMarkAsRead(override val data: DataLibrus,
Metadata.TYPE_ANNOUNCEMENT,
announcement.id,
announcement.seen,
announcement.notified,
announcement.addedDate
announcement.notified
))
onSuccess()
}

View File

@ -38,15 +38,17 @@ class LibrusApiAnnouncements(override val data: DataLibrus,
val read = announcement.getBoolean("WasRead") ?: false
val announcementObject = Announcement(
profileId,
id,
subject,
text,
startDate,
endDate,
teacherId,
longId
)
profileId = profileId,
id = id,
subject = subject,
text = text,
startDate = startDate,
endDate = endDate,
teacherId = teacherId,
addedDate = addedDate
).also {
it.idString = longId
}
data.announcementList.add(announcementObject)
data.setSeenMetadataList.add(Metadata(
@ -54,8 +56,7 @@ class LibrusApiAnnouncements(override val data: DataLibrus,
Metadata.TYPE_ANNOUNCEMENT,
id,
read,
profile.empty || read,
addedDate
profile.empty || read
))
}

View File

@ -26,25 +26,39 @@ class LibrusApiAttendanceTypes(override val data: DataLibrus,
attendanceTypes?.forEach { attendanceType ->
val id = attendanceType.getLong("Id") ?: return@forEach
val name = attendanceType.getString("Name") ?: ""
val color = attendanceType.getString("ColorRGB")?.let { Color.parseColor("#$it") } ?: -1
val standardId = when (attendanceType.getBoolean("Standard") ?: false) {
true -> id
false -> attendanceType.getJsonObject("StandardType")?.getLong("Id") ?: id
}
val type = when (standardId) {
val typeName = attendanceType.getString("Name") ?: ""
val typeSymbol = attendanceType.getString("Short") ?: ""
val typeColor = attendanceType.getString("ColorRGB")?.let { Color.parseColor("#$it") }
val isStandard = attendanceType.getBoolean("Standard") ?: false
val baseType = when (attendanceType.getJsonObject("StandardType")?.getLong("Id") ?: id) {
1L -> Attendance.TYPE_ABSENT
2L -> Attendance.TYPE_BELATED
3L -> Attendance.TYPE_ABSENT_EXCUSED
4L -> Attendance.TYPE_RELEASED
/*100*/else -> Attendance.TYPE_PRESENT
/*100*/else -> when (isStandard) {
true -> Attendance.TYPE_PRESENT
false -> Attendance.TYPE_PRESENT_CUSTOM
}
}
val typeShort = when (isStandard) {
true -> data.app.attendanceManager.getTypeShort(baseType)
false -> typeSymbol
}
data.attendanceTypes.put(id, AttendanceType(profileId, id, name, type, color))
data.attendanceTypes.put(id, AttendanceType(
profileId,
id,
baseType,
typeName,
typeShort,
typeSymbol,
typeColor
))
}
data.setSyncNext(ENDPOINT_LIBRUS_API_ATTENDANCE_TYPES, 4*DAY)
data.setSyncNext(ENDPOINT_LIBRUS_API_ATTENDANCE_TYPES, 2*DAY)
onSuccess(ENDPOINT_LIBRUS_API_ATTENDANCE_TYPES)
}
}

View File

@ -13,7 +13,6 @@ import pl.szczodrzynski.edziennik.data.db.entity.Attendance
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
import pl.szczodrzynski.edziennik.utils.models.Date
import pl.szczodrzynski.edziennik.utils.models.Time
class LibrusApiAttendances(override val data: DataLibrus,
override val lastSync: Long?,
@ -42,9 +41,9 @@ class LibrusApiAttendances(override val data: DataLibrus,
val lessonDate = Date.fromY_m_d(attendance.getString("Date"))
val teacherId = attendance.getJsonObject("AddedBy")?.getLong("Id")
val semester = attendance.getInt("Semester") ?: return@forEach
val type = attendance.getJsonObject("Type")?.getLong("Id") ?: return@forEach
val typeObject = data.attendanceTypes[type] ?: null
val topic = typeObject?.name ?: ""
val typeId = attendance.getJsonObject("Type")?.getLong("Id") ?: return@forEach
val type = data.attendanceTypes[typeId] ?: null
val startTime = data.lessonRanges.get(lessonNo)?.startTime
@ -52,29 +51,34 @@ class LibrusApiAttendances(override val data: DataLibrus,
data.librusLessons.singleOrNull { it.lessonId == lessonId }
else null
val attendanceObject = Attendance(
profileId,
id,
teacherId ?: lesson?.teacherId ?: -1,
lesson?.subjectId ?: -1,
semester,
topic,
lessonDate,
startTime ?: Time(0, 0, 0),
typeObject?.type ?: Attendance.TYPE_CUSTOM
)
val addedDate = Date.fromIso(attendance.getString("AddDate") ?: return@forEach)
val attendanceObject = Attendance(
profileId = profileId,
id = id,
baseType = type?.baseType ?: Attendance.TYPE_UNKNOWN,
typeName = type?.typeName ?: "nieznany rodzaj",
typeShort = type?.typeShort ?: "?",
typeSymbol = type?.typeSymbol ?: "?",
typeColor = type?.typeColor,
date = lessonDate,
startTime = startTime,
semester = semester,
teacherId = teacherId ?: lesson?.teacherId ?: -1,
subjectId = lesson?.subjectId ?: -1,
addedDate = addedDate
).also {
it.lessonNumber = lessonNo
}
data.attendanceList.add(attendanceObject)
if(typeObject?.type != Attendance.TYPE_PRESENT) {
if(type?.baseType != Attendance.TYPE_PRESENT) {
data.metadataList.add(Metadata(
profileId,
Metadata.TYPE_ATTENDANCE,
id,
profile?.empty ?: false,
profile?.empty ?: false,
addedDate
profile?.empty ?: false
))
}
}

View File

@ -55,7 +55,8 @@ class LibrusApiBehaviourGrades(override val data: DataLibrus,
comment = null,
semester = 1,
teacherId = -1,
subjectId = 1
subjectId = 1,
addedDate = profile.getSemesterStart(1).inMillis
)
data.gradeList.add(semester1StartGradeObject)
@ -64,8 +65,7 @@ class LibrusApiBehaviourGrades(override val data: DataLibrus,
Metadata.TYPE_GRADE,
semester1StartGradeObject.id,
true,
true,
profile.getSemesterStart(1).inMillis
true
))
}
@ -83,7 +83,8 @@ class LibrusApiBehaviourGrades(override val data: DataLibrus,
comment = null,
semester = 2,
teacherId = -1,
subjectId = 1
subjectId = 1,
addedDate = profile.getSemesterStart(2).inMillis
)
data.gradeList.add(semester2StartGradeObject)
@ -92,8 +93,7 @@ class LibrusApiBehaviourGrades(override val data: DataLibrus,
Metadata.TYPE_GRADE,
semester2StartGradeObject.id,
true,
true,
profile.getSemesterStart(2).inMillis
true
))
}
@ -155,7 +155,8 @@ class LibrusApiBehaviourGrades(override val data: DataLibrus,
comment = if (text != null) description.join(" - ") else null,
semester = semester,
teacherId = teacherId,
subjectId = 1
subjectId = 1,
addedDate = addedDate
).apply {
valueMax = valueTo
}
@ -166,8 +167,7 @@ class LibrusApiBehaviourGrades(override val data: DataLibrus,
Metadata.TYPE_GRADE,
id,
profile.empty,
profile.empty,
addedDate
profile.empty
))
}

View File

@ -65,7 +65,8 @@ class LibrusApiDescriptiveGrades(override val data: DataLibrus,
comment = null,
semester = semester,
teacherId = teacherId,
subjectId = subjectId
subjectId = subjectId,
addedDate = addedDate
)
data.gradeList.add(gradeObject)
@ -74,8 +75,7 @@ class LibrusApiDescriptiveGrades(override val data: DataLibrus,
Metadata.TYPE_GRADE,
id,
profile.empty,
profile.empty,
addedDate
profile.empty
))
}

View File

@ -56,7 +56,8 @@ class LibrusApiEvents(override val data: DataLibrus,
type = type,
teacherId = teacherId,
subjectId = subjectId,
teamId = teamId
teamId = teamId,
addedDate = addedDate
)
data.eventList.add(eventObject)
@ -66,8 +67,7 @@ class LibrusApiEvents(override val data: DataLibrus,
Metadata.TYPE_EVENT,
id,
profile?.empty ?: false,
profile?.empty ?: false,
addedDate
profile?.empty ?: false
))
}

View File

@ -79,7 +79,8 @@ class LibrusApiGrades(override val data: DataLibrus,
comment = null,
semester = semester,
teacherId = teacherId,
subjectId = subjectId
subjectId = subjectId,
addedDate = addedDate
)
grade.getJsonObject("Improvement")?.also {
@ -98,8 +99,7 @@ class LibrusApiGrades(override val data: DataLibrus,
Metadata.TYPE_GRADE,
id,
profile.empty,
profile.empty,
addedDate
profile.empty
))
}

View File

@ -43,7 +43,8 @@ class LibrusApiHomework(override val data: DataLibrus,
type = -1,
teacherId = teacherId,
subjectId = -1,
teamId = -1
teamId = -1,
addedDate = addedDate.inMillis
)
data.eventList.add(eventObject)
@ -52,8 +53,7 @@ class LibrusApiHomework(override val data: DataLibrus,
Metadata.TYPE_HOMEWORK,
id,
profile?.empty ?: false,
profile?.empty ?: false,
addedDate.inMillis
profile?.empty ?: false
))
}

View File

@ -33,9 +33,9 @@ class LibrusApiLuckyNumber(override val data: DataLibrus,
val luckyNumberDate = Date.fromY_m_d(luckyNumberEl.getString("LuckyNumberDay")) ?: Date.getToday()
val luckyNumber = luckyNumberEl.getInt("LuckyNumber") ?: -1
val luckyNumberObject = LuckyNumber(
profileId,
luckyNumberDate,
luckyNumber
profileId = profileId,
date = luckyNumberDate,
number = luckyNumber
)
if (luckyNumberDate >= Date.getToday())
@ -50,8 +50,7 @@ class LibrusApiLuckyNumber(override val data: DataLibrus,
Metadata.TYPE_LUCKY_NUMBER,
luckyNumberObject.date.value.toLong(),
true,
profile?.empty ?: false,
System.currentTimeMillis()
profile?.empty ?: false
))
}
}

View File

@ -46,12 +46,15 @@ class LibrusApiNotices(override val data: DataLibrus,
val semester = profile?.dateToSemester(addedDate) ?: 1
val noticeObject = Notice(
profileId,
id,
categoryText + "\n" + text,
semester,
type,
teacherId
profileId = profileId,
id = id,
type = type,
semester = semester,
text = text,
category = categoryText,
points = null,
teacherId = teacherId,
addedDate = addedDate.inMillis
)
data.noticeList.add(noticeObject)
@ -61,8 +64,7 @@ class LibrusApiNotices(override val data: DataLibrus,
Metadata.TYPE_NOTICE,
id,
profile?.empty ?: false,
profile?.empty ?: false,
addedDate.inMillis
profile?.empty ?: false
))
}

View File

@ -56,7 +56,8 @@ class LibrusApiPointGrades(override val data: DataLibrus,
comment = null,
semester = semester,
teacherId = teacherId,
subjectId = subjectId
subjectId = subjectId,
addedDate = addedDate
).apply {
valueMax = category?.valueTo ?: 0f
}
@ -67,8 +68,7 @@ class LibrusApiPointGrades(override val data: DataLibrus,
Metadata.TYPE_GRADE,
id,
profile.empty,
profile.empty,
addedDate
profile.empty
))
}

View File

@ -58,8 +58,7 @@ class LibrusApiPtMeetings(override val data: DataLibrus,
Metadata.TYPE_EVENT,
id,
profile?.empty ?: false,
profile?.empty ?: false,
System.currentTimeMillis()
profile?.empty ?: false
))
}

View File

@ -43,15 +43,15 @@ class LibrusApiTeacherFreeDays(override val data: DataLibrus,
val timeTo = teacherAbsence.getString("TimeTo")?.let { Time.fromH_m_s(it) }
val teacherAbsenceObject = TeacherAbsence(
profileId,
id,
teacherId,
type,
name,
dateFrom,
dateTo,
timeFrom,
timeTo
profileId = profileId,
id = id,
type = type,
name = name,
dateFrom = dateFrom,
dateTo = dateTo,
timeFrom = timeFrom,
timeTo = timeTo,
teacherId = teacherId
)
data.teacherAbsenceList.add(teacherAbsenceObject)
@ -60,8 +60,7 @@ class LibrusApiTeacherFreeDays(override val data: DataLibrus,
Metadata.TYPE_TEACHER_ABSENCE,
id,
true,
profile?.empty ?: false,
System.currentTimeMillis()
profile?.empty ?: false
))
}

View File

@ -60,7 +60,8 @@ class LibrusApiTextGrades(override val data: DataLibrus,
comment = grade.getString("Phrase") /* whatever it is */,
semester = semester,
teacherId = teacherId,
subjectId = subjectId
subjectId = subjectId,
addedDate = addedDate
)
data.gradeList.add(gradeObject)
@ -69,8 +70,7 @@ class LibrusApiTextGrades(override val data: DataLibrus,
Metadata.TYPE_GRADE,
id,
profile.empty,
profile.empty,
addedDate
profile.empty
))
}

View File

@ -198,8 +198,7 @@ class LibrusApiTimetables(override val data: DataLibrus,
Metadata.TYPE_LESSON_CHANGE,
lessonObject.id,
seen,
seen,
System.currentTimeMillis()
seen
))
}
data.lessonList.add(lessonObject)

View File

@ -97,7 +97,8 @@ class LibrusMessagesGetList(override val data: DataLibrus,
type = type,
subject = subject,
body = null,
senderId = senderId
senderId = senderId,
addedDate = sentDate
)
val messageRecipientObject = MessageRecipient(
@ -120,8 +121,7 @@ class LibrusMessagesGetList(override val data: DataLibrus,
Metadata.TYPE_MESSAGE,
id,
notified,
notified,
sentDate
notified
))
}

View File

@ -150,8 +150,7 @@ class LibrusMessagesGetMessage(override val data: DataLibrus,
Metadata.TYPE_MESSAGE,
messageObject.id,
true,
true,
messageObject.addedDate
true
))
}

View File

@ -50,7 +50,7 @@ class LibrusMessagesSendMessage(override val data: DataLibrus,
LibrusMessagesGetList(data, type = Message.TYPE_SENT, lastSync = null) {
val message = data.messageList.firstOrNull { it.type == Message.TYPE_SENT && it.id == id }
val metadata = data.metadataList.firstOrNull { it.thingType == Metadata.TYPE_MESSAGE && it.thingId == message?.id }
val event = MessageSentEvent(data.profileId, message, metadata?.addedDate)
val event = MessageSentEvent(data.profileId, message, message?.addedDate)
EventBus.getDefault().postSticky(event)
onSuccess()

View File

@ -58,7 +58,7 @@ class LibrusSynergiaHomework(override val data: DataLibrus,
elements[9].select("input").attr("onclick")
)?.get(1)?.toLong() ?: return@forEachIndexed
val lessons = data.db.timetableDao().getForDateNow(profileId, eventDate)
val lessons = data.db.timetableDao().getAllForDateNow(profileId, eventDate)
val startTime = lessons.firstOrNull { it.subjectId == subjectId }?.startTime
val seen = when (profile.empty) {
@ -76,7 +76,8 @@ class LibrusSynergiaHomework(override val data: DataLibrus,
type = Event.TYPE_HOMEWORK,
teacherId = teacherId,
subjectId = subjectId,
teamId = data.teamClass?.id ?: -1
teamId = data.teamClass?.id ?: -1,
addedDate = addedDate.inMillis
)
data.eventList.add(eventObject)
@ -85,8 +86,7 @@ class LibrusSynergiaHomework(override val data: DataLibrus,
Metadata.TYPE_HOMEWORK,
id,
seen,
seen,
addedDate.inMillis
seen
))
}
}

View File

@ -6,7 +6,10 @@ package pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.api
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik
import pl.szczodrzynski.edziennik.data.db.entity.Attendance
import pl.szczodrzynski.edziennik.data.db.entity.Attendance.*
import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_ABSENT
import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_ABSENT_EXCUSED
import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_PRESENT
import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_RELEASED
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
class MobidziennikApiAttendance(val data: DataMobidziennik, rows: List<String>) {
@ -23,7 +26,7 @@ class MobidziennikApiAttendance(val data: DataMobidziennik, rows: List<String>)
val id = cols[0].toLong()
val lessonId = cols[1].toLong()
data.mobiLessons.singleOrNull { it.id == lessonId }?.let { lesson ->
val type = when (cols[4]) {
val baseType = when (cols[4]) {
"2" -> TYPE_ABSENT
"5" -> TYPE_ABSENT_EXCUSED
"4" -> TYPE_RELEASED
@ -31,16 +34,37 @@ class MobidziennikApiAttendance(val data: DataMobidziennik, rows: List<String>)
}
val semester = data.profile?.dateToSemester(lesson.date) ?: 1
val typeName = when (baseType) {
TYPE_ABSENT -> "nieobecność"
TYPE_ABSENT_EXCUSED -> "nieobecność usprawiedliwiona"
TYPE_RELEASED -> "zwolnienie"
TYPE_PRESENT -> "obecność"
else -> "nieznany rodzaj"
}
val typeSymbol = when (baseType) {
TYPE_ABSENT -> "|"
TYPE_ABSENT_EXCUSED -> "+"
TYPE_RELEASED -> "z"
TYPE_PRESENT -> "."
else -> "?"
}
val attendanceObject = Attendance(
data.profileId,
id,
lesson.teacherId,
lesson.subjectId,
semester,
lesson.topic,
lesson.date,
lesson.startTime,
type)
profileId = data.profileId,
id = id,
baseType = baseType,
typeName = typeName,
typeShort = data.app.attendanceManager.getTypeShort(baseType),
typeSymbol = typeSymbol,
typeColor = null,
date = lesson.date,
startTime = lesson.startTime,
semester = semester,
teacherId = lesson.teacherId,
subjectId = lesson.subjectId
).also {
it.lessonTopic = lesson.topic
}
data.attendanceList.add(attendanceObject)
data.metadataList.add(
@ -49,8 +73,7 @@ class MobidziennikApiAttendance(val data: DataMobidziennik, rows: List<String>)
Metadata.TYPE_ATTENDANCE,
id,
data.profile?.empty ?: false,
data.profile?.empty ?: false,
System.currentTimeMillis()
data.profile?.empty ?: false
))
}
}

View File

@ -60,7 +60,9 @@ class MobidziennikApiEvents(val data: DataMobidziennik, rows: List<String>) {
type = type,
teacherId = teacherId,
subjectId = subjectId,
teamId = teamId)
teamId = teamId,
addedDate = addedDate
)
data.eventList.add(eventObject)
data.metadataList.add(
@ -69,8 +71,7 @@ class MobidziennikApiEvents(val data: DataMobidziennik, rows: List<String>) {
Metadata.TYPE_EVENT,
id,
data.profile?.empty ?: false,
data.profile?.empty ?: false,
addedDate
data.profile?.empty ?: false
))
}
}

View File

@ -79,7 +79,9 @@ class MobidziennikApiGrades(val data: DataMobidziennik, rows: List<String>) {
comment = null,
semester = semester,
teacherId = teacherId,
subjectId = subjectId)
subjectId = subjectId,
addedDate = addedDate
)
if (data.profile?.empty == true) {
addedDate = data.profile.dateSemester1Start.inMillis
@ -92,8 +94,7 @@ class MobidziennikApiGrades(val data: DataMobidziennik, rows: List<String>) {
Metadata.TYPE_GRADE,
id,
data.profile?.empty ?: false,
data.profile?.empty ?: false,
addedDate
data.profile?.empty ?: false
))
addedDate++
}

View File

@ -40,7 +40,8 @@ class MobidziennikApiHomework(val data: DataMobidziennik, rows: List<String>) {
type = Event.TYPE_HOMEWORK,
teacherId = teacherId,
subjectId = subjectId,
teamId = teamId)
teamId = teamId
)
data.eventList.add(eventObject)
data.metadataList.add(
@ -49,8 +50,7 @@ class MobidziennikApiHomework(val data: DataMobidziennik, rows: List<String>) {
Metadata.TYPE_HOMEWORK,
id,
data.profile?.empty ?: false,
data.profile?.empty ?: false,
System.currentTimeMillis()
data.profile?.empty ?: false
))
}
}

View File

@ -33,12 +33,16 @@ class MobidziennikApiNotices(val data: DataMobidziennik, rows: List<String>) {
val addedDate = Date.fromYmd(cols[7]).inMillis
val noticeObject = Notice(
data.profileId,
id,
text,
semester,
type,
teacherId)
profileId = data.profileId,
id = id,
type = type,
semester = semester,
text = text,
category = null,
points = null,
teacherId = teacherId,
addedDate = addedDate
)
data.noticeList.add(noticeObject)
data.metadataList.add(
@ -47,8 +51,7 @@ class MobidziennikApiNotices(val data: DataMobidziennik, rows: List<String>) {
Metadata.TYPE_NOTICE,
id,
data.profile?.empty ?: false,
data.profile?.empty ?: false,
addedDate
data.profile?.empty ?: false
))
}
}}

View File

@ -8,9 +8,9 @@ import android.util.SparseArray
import androidx.core.util.set
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik
import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
import pl.szczodrzynski.edziennik.data.db.entity.Lesson
import pl.szczodrzynski.edziennik.data.db.entity.LessonRange
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.entity.Lesson
import pl.szczodrzynski.edziennik.fixName
import pl.szczodrzynski.edziennik.keys
import pl.szczodrzynski.edziennik.singleOrNull
@ -97,8 +97,7 @@ class MobidziennikApiTimetable(val data: DataMobidziennik, rows: List<String>) {
Metadata.TYPE_LESSON_CHANGE,
it.id,
seen,
seen,
System.currentTimeMillis()
seen
))
}
data.lessonList += it

View File

@ -17,9 +17,9 @@ class MobidziennikLuckyNumberExtractor(val data: DataMobidziennik, text: String)
val luckyNumber = it.groupValues[1].toInt()
val luckyNumberObject = LuckyNumber(
data.profileId,
Date.getToday(),
luckyNumber
profileId = data.profileId,
date = Date.getToday(),
number = luckyNumber
)
data.luckyNumberList.add(luckyNumberObject)
@ -29,8 +29,7 @@ class MobidziennikLuckyNumberExtractor(val data: DataMobidziennik, text: String)
Metadata.TYPE_LUCKY_NUMBER,
luckyNumberObject.date.value.toLong(),
true,
data.profile?.empty ?: false,
System.currentTimeMillis()
data.profile?.empty ?: false
))
} catch (_: Exception){}
}

View File

@ -11,7 +11,12 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.ENDPOINT_MOBID
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.MobidziennikWeb
import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
import pl.szczodrzynski.edziennik.data.db.entity.Attendance
import pl.szczodrzynski.edziennik.data.db.entity.Attendance.*
import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_ABSENT
import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_ABSENT_EXCUSED
import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_BELATED
import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_PRESENT
import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_RELEASED
import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_UNKNOWN
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
import pl.szczodrzynski.edziennik.fixName
@ -71,6 +76,18 @@ class MobidziennikWebAttendance(override val data: DataMobidziennik,
val start = System.currentTimeMillis()
val types = Regexes.MOBIDZIENNIK_ATTENDANCE_TYPES
.find(text)
?.get(1)
?.split("<br/>")
?.map {
it.trimEnd(',')
.split(" ", limit = 2)
.let { it.getOrNull(0) to it.getOrNull(1) }
}
?.toMap()
val typeSymbols = types?.keys?.filterNotNull() ?: listOf()
Regexes.MOBIDZIENNIK_ATTENDANCE_TABLE.findAll(text).forEach { tableResult ->
val table = tableResult[1]
val lessonDates = mutableListOf<Date>()
@ -92,14 +109,14 @@ class MobidziennikWebAttendance(override val data: DataMobidziennik,
return@forEach
ranges.forEach { range ->
val lessonDate = dateIterator.next()
val entry = entriesIterator.next()
var entry = entriesIterator.next()
if (entry.isBlank())
return@forEach
val startTime = Time.fromH_m(range[1])
val entryIterator = entry.iterator()
range[2].split(" / ").mapNotNull { Regexes.MOBIDZIENNIK_ATTENDANCE_LESSON.find(it) }.forEachIndexed { index, lesson ->
val topic = lesson[2]
if (topic.startsWith("Lekcja odwołana: ") || !entryIterator.hasNext())
if (topic.startsWith("Lekcja odwołana: ") || entry.isEmpty())
return@forEachIndexed
val subjectName = lesson[1]
//val team = lesson[3]
@ -108,39 +125,58 @@ class MobidziennikWebAttendance(override val data: DataMobidziennik,
val teacherId = data.teacherList.singleOrNull { it.fullNameLastFirst == teacherName }?.id ?: -1
val subjectId = data.subjectList.singleOrNull { it.longName == subjectName }?.id ?: -1
val type = when (entryIterator.nextChar()) {
'.' -> TYPE_PRESENT
'|' -> TYPE_ABSENT
'+' -> TYPE_ABSENT_EXCUSED
's' -> TYPE_BELATED
'z' -> TYPE_RELEASED
else -> TYPE_PRESENT
var typeSymbol = ""
for (symbol in typeSymbols) {
if (entry.startsWith(symbol) && symbol.length > typeSymbol.length)
typeSymbol = symbol
}
entry = entry.removePrefix(typeSymbol)
val baseType = when (typeSymbol) {
"." -> TYPE_PRESENT
"|" -> TYPE_ABSENT
"+" -> TYPE_ABSENT_EXCUSED
"s" -> TYPE_BELATED
"z" -> TYPE_RELEASED
else -> TYPE_UNKNOWN
}
val typeName = types?.get(typeSymbol) ?: ""
val typeShort = when (baseType) {
TYPE_UNKNOWN -> typeSymbol
else -> data.app.attendanceManager.getTypeShort(baseType)
}
val semester = data.profile?.dateToSemester(lessonDate) ?: 1
val id = lessonDate.combineWith(startTime) / 6L * 10L + (lesson[0].hashCode() and 0xFFFF) + index
val attendanceObject = Attendance(
data.profileId,
id,
teacherId,
subjectId,
semester,
topic,
lessonDate,
startTime,
type)
profileId = profileId,
id = id,
baseType = baseType,
typeName = typeName,
typeShort = typeShort,
typeSymbol = typeSymbol,
typeColor = null,
date = lessonDate,
startTime = startTime,
semester = semester,
teacherId = teacherId,
subjectId = subjectId
).also {
it.lessonTopic = topic
}
data.attendanceList.add(attendanceObject)
if (type != TYPE_PRESENT) {
if (baseType != TYPE_PRESENT) {
data.metadataList.add(
Metadata(
data.profileId,
Metadata.TYPE_ATTENDANCE,
id,
data.profile?.empty ?: false,
data.profile?.empty ?: false,
System.currentTimeMillis()
data.profile?.empty ?: false
))
}
}

View File

@ -89,8 +89,8 @@ class MobidziennikWebCalendar(override val data: DataMobidziennik,
Metadata.TYPE_EVENT,
eventObject.id,
profile?.empty ?: false,
profile?.empty ?: false,
System.currentTimeMillis() /* no addedDate here though */
profile?.empty ?: false
/* no addedDate here though */
))
}
}

View File

@ -139,8 +139,7 @@ class MobidziennikWebGetMessage(override val data: DataMobidziennik,
Metadata.TYPE_MESSAGE,
message.id,
true,
true,
message.addedDate
true
))
}

View File

@ -125,7 +125,8 @@ class MobidziennikWebGrades(override val data: DataMobidziennik,
comment = null,
semester = gradeSemester,
teacherId = teacherId,
subjectId = subjectId
subjectId = subjectId,
addedDate = gradeAddedDateMillis
)
gradeObject.classAverage = gradeClassAverage
@ -137,8 +138,7 @@ class MobidziennikWebGrades(override val data: DataMobidziennik,
Metadata.TYPE_GRADE,
gradeObject.id,
profile.empty,
profile.empty,
gradeAddedDateMillis
profile.empty
))
}
}

View File

@ -77,11 +77,12 @@ class MobidziennikWebMessagesAll(override val data: DataMobidziennik,
type = type,
subject = subject,
body = null,
senderId = senderId
senderId = senderId,
addedDate = addedDate
)
data.messageList.add(message)
data.metadataList.add(Metadata(profileId, Metadata.TYPE_MESSAGE, message.id, true, true, addedDate))
data.metadataList.add(Metadata(profileId, Metadata.TYPE_MESSAGE, message.id, true, true))
}
// sync every 7 days as we probably don't expect more than

View File

@ -63,7 +63,8 @@ class MobidziennikWebMessagesInbox(override val data: DataMobidziennik,
type = Message.TYPE_RECEIVED,
subject = subject,
body = null,
senderId = senderId
senderId = senderId,
addedDate = addedDate
)
if (hasAttachments)
@ -76,8 +77,7 @@ class MobidziennikWebMessagesInbox(override val data: DataMobidziennik,
Metadata.TYPE_MESSAGE,
message.id,
isRead,
isRead || profile?.empty ?: false,
addedDate
isRead || profile?.empty ?: false
))
}

View File

@ -78,7 +78,8 @@ class MobidziennikWebMessagesSent(override val data: DataMobidziennik,
type = Message.TYPE_SENT,
subject = subject,
body = null,
senderId = null
senderId = null,
addedDate = addedDate
)
if (hasAttachments)
@ -91,8 +92,7 @@ class MobidziennikWebMessagesSent(override val data: DataMobidziennik,
Metadata.TYPE_MESSAGE,
message.id,
true,
true,
addedDate
true
))
}

View File

@ -45,7 +45,7 @@ class MobidziennikWebSendMessage(override val data: DataMobidziennik,
MobidziennikWebMessagesAll(data, null) {
val message = data.messageList.firstOrNull { it.type == Message.TYPE_SENT && it.subject == subject }
val metadata = data.metadataList.firstOrNull { it.thingType == Metadata.TYPE_MESSAGE && it.thingId == message?.id }
val event = MessageSentEvent(data.profileId, message, metadata?.addedDate)
val event = MessageSentEvent(data.profileId, message, message?.addedDate)
EventBus.getDefault().postSticky(event)
onSuccess()

View File

@ -7,7 +7,7 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.ENDPOINT_VULCAN_API_ATTENDANCE
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanApi
import pl.szczodrzynski.edziennik.data.db.entity.Attendance
import pl.szczodrzynski.edziennik.data.db.entity.Attendance.TYPE_PRESENT
import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_PRESENT
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
import pl.szczodrzynski.edziennik.utils.models.Date
@ -38,38 +38,43 @@ class VulcanApiAttendance(override val data: DataVulcan,
json.getJsonObject("Data")?.getJsonArray("Frekwencje")?.forEach { attendanceEl ->
val attendance = attendanceEl.asJsonObject
val attendanceCategory = data.attendanceTypes.get(attendance.getLong("IdKategoria") ?: return@forEach)
val type = data.attendanceTypes.get(attendance.getLong("IdKategoria") ?: return@forEach)
?: return@forEach
val type = attendanceCategory.type
val id = (attendance.getInt("Dzien") ?: 0) + (attendance.getInt("Numer") ?: 0)
val lessonDateMillis = Date.fromY_m_d(attendance.getString("DzienTekst")).inMillis
val lessonDate = Date.fromMillis(lessonDateMillis)
val startTime = data.lessonRanges.get(attendance.getInt("Numer") ?: 0)?.startTime
val lessonSemester = profile.dateToSemester(lessonDate)
val attendanceObject = Attendance(
profileId,
id.toLong(),
-1,
attendance.getLong("IdPrzedmiot") ?: -1,
lessonSemester,
attendance.getString("PrzedmiotNazwa") + attendanceCategory.name.let { " - $it" },
lessonDate,
data.lessonRanges.get(attendance.getInt("Numer") ?: 0)?.startTime,
type)
profileId = profileId,
id = id.toLong(),
baseType = type.baseType,
typeName = type.typeName,
typeShort = type.typeShort,
typeSymbol = type.typeSymbol,
typeColor = type.typeColor,
date = lessonDate,
startTime = startTime,
semester = lessonSemester,
teacherId = -1,
subjectId = attendance.getLong("IdPrzedmiot") ?: -1,
addedDate = lessonDate.combineWith(startTime)
).also {
it.lessonNumber = attendance.getInt("Numer")
}
data.attendanceList.add(attendanceObject)
if (attendanceObject.type != TYPE_PRESENT) {
if (type.baseType != TYPE_PRESENT) {
data.metadataList.add(Metadata(
profileId,
Metadata.TYPE_ATTENDANCE,
attendanceObject.id,
profile.empty,
profile.empty,
attendanceObject.lessonDate.combineWith(attendanceObject.startTime)
profile.empty
))
}
}

View File

@ -114,11 +114,11 @@ class VulcanApiDictionaries(override val data: DataVulcan,
private fun saveAttendanceType(attendanceType: JsonObject) {
val id = attendanceType.getLong("Id") ?: return
val name = attendanceType.getString("Nazwa") ?: ""
val typeName = attendanceType.getString("Nazwa") ?: ""
val absent = attendanceType.getBoolean("Nieobecnosc") ?: false
val excused = attendanceType.getBoolean("Usprawiedliwione") ?: false
val type = if (absent) {
val baseType = if (absent) {
if (excused)
Attendance.TYPE_ABSENT_EXCUSED
else
@ -137,15 +137,35 @@ class VulcanApiDictionaries(override val data: DataVulcan,
else if (present)
Attendance.TYPE_PRESENT
else
Attendance.TYPE_CUSTOM
Attendance.TYPE_UNKNOWN
}
val (typeColor, typeSymbol) = when (id.toInt()) {
1 -> 0xffffffff to "" // obecność
2 -> 0xffffa687 to "" // nieobecność
3 -> 0xfffcc150 to "u" // nieobecność usprawiedliwiona
4 -> 0xffede049 to "s" // spóźnienie
5 -> 0xffbbdd5f to "su" // spóźnienie usprawiedliwione
6 -> 0xffa9c9fd to "ns" // nieobecny z przyczyn szkolnych
7 -> 0xffddbbe5 to "z" // zwolniony
8 -> 0xffffffff to "" // usunięty wpis
else -> null to "?"
}
val typeShort = when (id.toInt()) {
6 -> "ns" // nieobecny z przyczyn szkolnych
8 -> "" // usunięty wpis
else -> data.app.attendanceManager.getTypeShort(baseType)
}
val attendanceTypeObject = AttendanceType(
profileId,
id,
name,
type,
-1
baseType,
typeName,
typeShort,
typeSymbol,
typeColor?.toInt()
)
data.attendanceTypes.put(id, attendanceTypeObject)

View File

@ -59,7 +59,7 @@ class VulcanApiEvents(override val data: DataVulcan,
val teacherId = event.getLong("IdPracownik") ?: -1
val topic = event.getString("Opis")?.trim() ?: ""
val lessonList = data.db.timetableDao().getForDateNow(profileId, eventDate)
val lessonList = data.db.timetableDao().getAllForDateNow(profileId, eventDate)
val startTime = lessonList.firstOrNull { it.subjectId == subjectId }?.startTime
val type = when (isHomework) {
@ -90,8 +90,7 @@ class VulcanApiEvents(override val data: DataVulcan,
if (isHomework) Metadata.TYPE_HOMEWORK else Metadata.TYPE_EVENT,
id,
profile.empty,
profile.empty,
System.currentTimeMillis()
profile.empty
))
}

View File

@ -101,7 +101,8 @@ class VulcanApiGrades(override val data: DataVulcan,
comment = null,
semester = data.studentSemesterNumber,
teacherId = teacherId,
subjectId = subjectId
subjectId = subjectId,
addedDate = addedDate
)
data.gradeList.add(gradeObject)
@ -110,9 +111,7 @@ class VulcanApiGrades(override val data: DataVulcan,
Metadata.TYPE_GRADE,
id,
profile.empty,
profile.empty,
addedDate
profile.empty
))
}

View File

@ -37,8 +37,7 @@ class VulcanApiMessagesChangeStatus(override val data: DataVulcan,
Metadata.TYPE_MESSAGE,
messageObject.id,
true,
true,
messageObject.addedDate
true
))
messageObject.seen = true

View File

@ -72,7 +72,8 @@ class VulcanApiMessagesInbox(override val data: DataVulcan,
type = TYPE_RECEIVED,
subject = subject,
body = body.replace("\n", "<br>"),
senderId = senderId
senderId = senderId,
addedDate = sentDate
)
val messageRecipientObject = MessageRecipient(
@ -90,8 +91,7 @@ class VulcanApiMessagesInbox(override val data: DataVulcan,
Metadata.TYPE_MESSAGE,
id,
readDate > 0,
readDate > 0,
sentDate
readDate > 0
))
}

View File

@ -97,7 +97,8 @@ class VulcanApiMessagesSent(override val data: DataVulcan,
type = TYPE_SENT,
subject = subject,
body = body.replace("\n", "<br>"),
senderId = null
senderId = null,
addedDate = sentDate
)
data.messageList.add(messageObject)
@ -106,8 +107,7 @@ class VulcanApiMessagesSent(override val data: DataVulcan,
Metadata.TYPE_MESSAGE,
id,
true,
true,
sentDate
true
))
}

View File

@ -16,7 +16,6 @@ import pl.szczodrzynski.edziennik.getJsonArray
import pl.szczodrzynski.edziennik.getLong
import pl.szczodrzynski.edziennik.getString
import pl.szczodrzynski.edziennik.toSparseArray
import pl.szczodrzynski.edziennik.utils.models.Date
class VulcanApiNotices(override val data: DataVulcan,
override val lastSync: Long?,
@ -41,15 +40,21 @@ class VulcanApiNotices(override val data: DataVulcan,
val id = notice.getLong("Id") ?: return@forEach
val text = notice.getString("TrescUwagi") ?: return@forEach
val teacherId = notice.getLong("IdPracownik") ?: -1
val addedDate = Date.fromY_m_d(notice.getString("DataWpisuTekst")).inMillis
val addedDate = notice.getLong("DataModyfikacji")?.times(1000) ?: System.currentTimeMillis()
val categoryId = notice.getLong("IdKategoriaUwag") ?: -1
val categoryText = data.noticeTypes[categoryId]?.name ?: ""
val noticeObject = Notice(
profileId,
id,
text,
profile.currentSemester,
Notice.TYPE_NEUTRAL,
teacherId
profileId = profileId,
id = id,
type = Notice.TYPE_NEUTRAL,
semester = profile.currentSemester,
text = text,
category = categoryText,
points = null,
teacherId = teacherId,
addedDate = addedDate
)
data.noticeList.add(noticeObject)
@ -58,8 +63,7 @@ class VulcanApiNotices(override val data: DataVulcan,
Metadata.TYPE_NOTICE,
id,
profile.empty,
profile.empty,
addedDate
profile.empty
))
}

View File

@ -82,8 +82,7 @@ class VulcanApiProposedGrades(override val data: DataVulcan,
Metadata.TYPE_GRADE,
gradeObject.id,
data.profile?.empty ?: false,
data.profile?.empty ?: false,
System.currentTimeMillis()
data.profile?.empty ?: false
))
}
}

View File

@ -54,7 +54,7 @@ class VulcanApiSendMessage(override val data: DataVulcan,
VulcanApiMessagesSent(data, null) {
val message = data.messageList.firstOrNull { it.type == Message.TYPE_SENT && it.subject == subject }
val metadata = data.metadataList.firstOrNull { it.thingType == Metadata.TYPE_MESSAGE && it.thingId == messageId }
val event = MessageSentEvent(data.profileId, message, metadata?.addedDate)
val event = MessageSentEvent(data.profileId, message, message?.addedDate)
EventBus.getDefault().postSticky(event)
onSuccess()

View File

@ -184,8 +184,7 @@ class VulcanApiTimetable(override val data: DataVulcan,
Metadata.TYPE_LESSON_CHANGE,
lessonObject.id,
seen,
seen,
System.currentTimeMillis()
seen
))
}

View File

@ -88,6 +88,7 @@ abstract class Data(val app: App, val profile: Profile?, val loginStore: LoginSt
var teacherOnConflictStrategy = OnConflictStrategy.IGNORE
var eventListReplace = false
var messageListReplace = false
var announcementListReplace = false
val classrooms = LongSparseArray<Classroom>()
val attendanceTypes = LongSparseArray<AttendanceType>()
@ -120,7 +121,6 @@ abstract class Data(val app: App, val profile: Profile?, val loginStore: LoginSt
val attendanceList = mutableListOf<Attendance>()
val announcementList = mutableListOf<Announcement>()
val announcementIgnoreList = mutableListOf<Announcement>()
val luckyNumberList = mutableListOf<LuckyNumber>()
@ -178,7 +178,6 @@ abstract class Data(val app: App, val profile: Profile?, val loginStore: LoginSt
noticeList.clear()
attendanceList.clear()
announcementList.clear()
announcementIgnoreList.clear()
luckyNumberList.clear()
teacherAbsenceList.clear()
messageList.clear()
@ -284,39 +283,19 @@ abstract class Data(val app: App, val profile: Profile?, val loginStore: LoginSt
d("Metadata saved in ${System.currentTimeMillis()-startTime} ms")
startTime = System.currentTimeMillis()
if (lessonList.isNotEmpty()) {
db.timetableDao() += lessonList
}
if (gradeList.isNotEmpty()) {
db.gradeDao().addAll(gradeList)
}
if (eventList.isNotEmpty()) {
if (eventListReplace)
db.eventDao().replaceAll(eventList)
else
db.eventDao().upsertAll(eventList, removeNotKept = true)
}
db.timetableDao().putAll(lessonList, removeNotKept = true)
db.gradeDao().putAll(gradeList, removeNotKept = true)
db.eventDao().putAll(eventList, forceReplace = eventListReplace, removeNotKept = true)
if (noticeList.isNotEmpty()) {
db.noticeDao().clear(profile.id)
db.noticeDao().addAll(noticeList)
db.noticeDao().putAll(noticeList)
}
if (attendanceList.isNotEmpty())
db.attendanceDao().addAll(attendanceList)
if (announcementList.isNotEmpty())
db.announcementDao().addAll(announcementList)
if (announcementIgnoreList.isNotEmpty())
db.announcementDao().addAllIgnore(announcementIgnoreList)
if (luckyNumberList.isNotEmpty())
db.luckyNumberDao().addAll(luckyNumberList)
if (teacherAbsenceList.isNotEmpty())
db.teacherAbsenceDao().addAll(teacherAbsenceList)
db.attendanceDao().putAll(attendanceList, removeNotKept = true)
db.announcementDao().putAll(announcementList, forceReplace = announcementListReplace, removeNotKept = false)
db.luckyNumberDao().putAll(luckyNumberList)
db.teacherAbsenceDao().putAll(teacherAbsenceList)
if (messageList.isNotEmpty()) {
if (messageListReplace)
db.messageDao().replaceAll(messageList)
else
db.messageDao().upsertAll(messageList, removeNotKept = false) // TODO dataRemoveModel for messages
}
db.messageDao().putAll(messageList, forceReplace = messageListReplace, removeNotKept = false)
if (messageRecipientList.isNotEmpty())
db.messageRecipientDao().addAll(messageRecipientList)
if (messageRecipientIgnoreList.isNotEmpty())
@ -357,7 +336,7 @@ abstract class Data(val app: App, val profile: Profile?, val loginStore: LoginSt
}
fun shouldSyncLuckyNumber(): Boolean {
return (db.luckyNumberDao().getNearestFutureNow(profileId, Date.getToday().value) ?: -1) == -1
return db.luckyNumberDao().getNearestFutureNow(profileId, Date.getToday()) == null
}
/*fun error(tag: String, errorCode: Int, response: Response? = null, throwable: Throwable? = null, apiResponse: JsonObject? = null) {

View File

@ -20,10 +20,10 @@ open class DataRemoveModel {
fun commit(profileId: Int, dao: TimetableDao) {
if (dateFrom != null && dateTo != null) {
dao.clearBetweenDates(profileId, dateFrom, dateTo)
dao.dontKeepBetweenDates(profileId, dateFrom, dateTo)
} else {
dateFrom?.let { dateFrom -> dao.clearFromDate(profileId, dateFrom) }
dateTo?.let { dateTo -> dao.clearToDate(profileId, dateTo) }
dateFrom?.let { dateFrom -> dao.dontKeepFromDate(profileId, dateFrom) }
dateTo?.let { dateTo -> dao.dontKeepToDate(profileId, dateTo) }
}
}
}
@ -69,7 +69,7 @@ open class DataRemoveModel {
fun commit(profileId: Int, dao: AttendanceDao) {
if (dateFrom != null) {
dao.clearAfterDate(profileId, dateFrom)
dao.dontKeepAfterDate(profileId, dateFrom)
}
}
}

View File

@ -40,8 +40,7 @@ class AppSync(val app: App, val notifications: MutableList<Notification>, val pr
Metadata.TYPE_EVENT,
event.id,
isPast || markAsSeen || event.seen,
isPast || markAsSeen || event.notified,
event.addedDate
isPast || markAsSeen || event.notified
)
})
return app.db.eventDao().upsertAll(events).size

View File

@ -53,7 +53,7 @@ class Notifications(val app: App, val notifications: MutableList<Notification>,
profileId = lesson.profileId,
profileName = profiles.singleOrNull { it.id == lesson.profileId }?.name,
viewId = MainActivity.DRAWER_ITEM_TIMETABLE,
addedDate = lesson.addedDate
addedDate = System.currentTimeMillis()
).addExtra("timetableDate", lesson.displayDate?.stringY_m_d ?: "")
}
}
@ -117,7 +117,7 @@ class Notifications(val app: App, val notifications: MutableList<Notification>,
}
private fun gradeNotifications() {
for (grade in app.db.gradeDao().notNotifiedNow) {
for (grade in app.db.gradeDao().getNotNotifiedNow()) {
val gradeName = when (grade.type) {
Grade.TYPE_SEMESTER1_PROPOSED, Grade.TYPE_SEMESTER2_PROPOSED -> app.getString(R.string.grade_semester_proposed_format_2, grade.name)
Grade.TYPE_SEMESTER1_FINAL, Grade.TYPE_SEMESTER2_FINAL -> app.getString(R.string.grade_semester_final_format_2, grade.name)
@ -144,7 +144,7 @@ class Notifications(val app: App, val notifications: MutableList<Notification>,
}
private fun behaviourNotifications() {
for (notice in app.db.noticeDao().notNotifiedNow) {
for (notice in app.db.noticeDao().getNotNotifiedNow()) {
val noticeTypeStr = when (notice.type) {
Notice.TYPE_POSITIVE -> app.getString(R.string.notification_notice_praise)
@ -155,7 +155,7 @@ class Notifications(val app: App, val notifications: MutableList<Notification>,
val text = app.getString(
R.string.notification_notice_format,
noticeTypeStr,
notice.teacherFullName,
notice.teacherName,
Date.fromMillis(notice.addedDate).formattedString
)
notifications += Notification(
@ -172,9 +172,9 @@ class Notifications(val app: App, val notifications: MutableList<Notification>,
}
private fun attendanceNotifications() {
for (attendance in app.db.attendanceDao().notNotifiedNow) {
for (attendance in app.db.attendanceDao().getNotNotifiedNow()) {
val attendanceTypeStr = when (attendance.type) {
val attendanceTypeStr = when (attendance.baseType) {
Attendance.TYPE_ABSENT -> app.getString(R.string.notification_absence)
Attendance.TYPE_ABSENT_EXCUSED -> app.getString(R.string.notification_absence_excused)
Attendance.TYPE_BELATED -> app.getString(R.string.notification_belated)
@ -191,7 +191,7 @@ class Notifications(val app: App, val notifications: MutableList<Notification>,
R.string.notification_attendance_format,
attendanceTypeStr,
attendance.subjectLongName,
attendance.lessonDate.formattedString
attendance.date.formattedString
)
notifications += Notification(
id = Notification.buildId(attendance.profileId, Notification.TYPE_NEW_ATTENDANCE, attendance.id),
@ -207,10 +207,10 @@ class Notifications(val app: App, val notifications: MutableList<Notification>,
}
private fun announcementNotifications() {
for (announcement in app.db.announcementDao().notNotifiedNow) {
for (announcement in app.db.announcementDao().getNotNotifiedNow()) {
val text = app.getString(
R.string.notification_announcement_format,
announcement.teacherFullName,
announcement.teacherName,
announcement.subject
)
notifications += Notification(
@ -247,9 +247,9 @@ class Notifications(val app: App, val notifications: MutableList<Notification>,
}
private fun luckyNumberNotifications() {
val luckyNumbers = app.db.luckyNumberDao().notNotifiedNow
luckyNumbers?.removeAll { it.date < today }
luckyNumbers?.forEach { luckyNumber ->
val luckyNumbers = app.db.luckyNumberDao().getNotNotifiedNow().toMutableList()
luckyNumbers.removeAll { it.date < today }
luckyNumbers.forEach { luckyNumber ->
val profile = profiles.singleOrNull { it.id == luckyNumber.profileId } ?: return@forEach
val text = when (profile.studentNumber != -1 && profile.studentNumber == luckyNumber.number) {
true -> when (luckyNumber.date.value) {
@ -271,7 +271,7 @@ class Notifications(val app: App, val notifications: MutableList<Notification>,
profileId = luckyNumber.profileId,
profileName = profile.name,
viewId = MainActivity.DRAWER_ITEM_HOME,
addedDate = luckyNumber.addedDate
addedDate = System.currentTimeMillis()
)
}
}
@ -280,7 +280,7 @@ class Notifications(val app: App, val notifications: MutableList<Notification>,
for (teacherAbsence in app.db.teacherAbsenceDao().getNotNotifiedNow()) {
val message = app.getString(
R.string.notification_teacher_absence_new_format,
teacherAbsence.teacherFullName
teacherAbsence.teacherName
)
notifications += Notification(
id = Notification.buildId(teacherAbsence.profileId, Notification.TYPE_TEACHER_ABSENCE, teacherAbsence.id),

View File

@ -43,7 +43,7 @@ import pl.szczodrzynski.edziennik.data.db.migration.*
LibrusLesson::class,
TimetableManual::class,
Metadata::class
], version = 85)
], version = 86)
@TypeConverters(
ConverterTime::class,
ConverterDate::class,
@ -170,7 +170,8 @@ abstract class AppDb : RoomDatabase() {
Migration82(),
Migration83(),
Migration84(),
Migration85()
Migration85(),
Migration86()
).allowMainThreadQueries().build()
}
}

View File

@ -1,82 +0,0 @@
/*
* Copyright (c) Kacper Ziubryniewicz 2020-1-6
*/
package pl.szczodrzynski.edziennik.data.db.dao;
import androidx.lifecycle.LiveData;
import androidx.room.Dao;
import androidx.room.Insert;
import androidx.room.OnConflictStrategy;
import androidx.room.Query;
import androidx.room.RawQuery;
import androidx.sqlite.db.SimpleSQLiteQuery;
import androidx.sqlite.db.SupportSQLiteQuery;
import java.util.List;
import pl.szczodrzynski.edziennik.data.db.entity.Announcement;
import pl.szczodrzynski.edziennik.data.db.entity.Metadata;
import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull;
import static pl.szczodrzynski.edziennik.data.db.entity.Metadata.TYPE_ANNOUNCEMENT;
@Dao
public abstract class AnnouncementDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
public abstract long add(Announcement announcement);
@Insert(onConflict = OnConflictStrategy.REPLACE)
public abstract void addAll(List<Announcement> announcementList);
@Insert(onConflict = OnConflictStrategy.IGNORE)
public abstract void addAllIgnore(List<Announcement> announcementList);
@Query("DELETE FROM announcements WHERE profileId = :profileId")
public abstract void clear(int profileId);
@RawQuery(observedEntities = {Announcement.class, Metadata.class})
abstract LiveData<List<AnnouncementFull>> getAll(SupportSQLiteQuery query);
public LiveData<List<AnnouncementFull>> getAll(int profileId, String filter) {
return getAll(new SimpleSQLiteQuery("SELECT \n" +
"*, \n" +
"teachers.teacherName || ' ' || teachers.teacherSurname AS teacherFullName\n" +
"FROM announcements \n" +
"LEFT JOIN teachers USING(profileId, teacherId)\n" +
"LEFT JOIN metadata ON announcementId = thingId AND thingType = "+TYPE_ANNOUNCEMENT+" AND metadata.profileId = "+profileId+"\n" +
"WHERE announcements.profileId = "+profileId+" AND "+filter+"\n" +
"ORDER BY addedDate DESC"));
}
public LiveData<List<AnnouncementFull>> getAll(int profileId) {
return getAll(profileId, "1");
}
public LiveData<List<AnnouncementFull>> getAllWhere(int profileId, String filter) {
return getAll(profileId, filter);
}
@RawQuery(observedEntities = {Announcement.class, Metadata.class})
abstract List<AnnouncementFull> getAllNow(SupportSQLiteQuery query);
public List<AnnouncementFull> getAllNow(int profileId, String filter) {
return getAllNow(new SimpleSQLiteQuery("SELECT \n" +
"*, \n" +
"teachers.teacherName || ' ' || teachers.teacherSurname AS teacherFullName\n" +
"FROM announcements \n" +
"LEFT JOIN teachers USING(profileId, teacherId)\n" +
"LEFT JOIN metadata ON announcementId = thingId AND thingType = "+TYPE_ANNOUNCEMENT+" AND metadata.profileId = "+profileId+"\n" +
"WHERE announcements.profileId = "+profileId+" AND "+filter+"\n" +
"ORDER BY addedDate DESC"));
}
public List<AnnouncementFull> getNotNotifiedNow(int profileId) {
return getAllNow(profileId, "notified = 0");
}
@Query("SELECT " +
"*, " +
"teachers.teacherName || ' ' || teachers.teacherSurname AS teacherFullName " +
"FROM announcements " +
"LEFT JOIN teachers USING(profileId, teacherId) " +
"LEFT JOIN metadata ON announcementId = thingId AND thingType = "+TYPE_ANNOUNCEMENT+" AND metadata.profileId = announcements.profileId " +
"WHERE notified = 0 " +
"ORDER BY addedDate DESC")
public abstract List<AnnouncementFull> getNotNotifiedNow();
}

View File

@ -0,0 +1,69 @@
/*
* Copyright (c) Kuba Szczodrzyński 2020-4-25.
*/
package pl.szczodrzynski.edziennik.data.db.dao
import androidx.lifecycle.LiveData
import androidx.room.Dao
import androidx.room.Query
import androidx.room.RawQuery
import androidx.sqlite.db.SupportSQLiteQuery
import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.annotation.SelectiveDao
import pl.szczodrzynski.edziennik.annotation.UpdateSelective
import pl.szczodrzynski.edziennik.data.db.AppDb
import pl.szczodrzynski.edziennik.data.db.entity.Announcement
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull
@Dao
@SelectiveDao(db = AppDb::class)
abstract class AnnouncementDao : BaseDao<Announcement, AnnouncementFull> {
companion object {
private const val QUERY = """
SELECT
*,
teachers.teacherName ||" "|| teachers.teacherSurname AS teacherName
FROM announcements
LEFT JOIN teachers USING(profileId, teacherId)
LEFT JOIN metadata ON announcementId = thingId AND thingType = ${Metadata.TYPE_ANNOUNCEMENT} AND metadata.profileId = announcements.profileId
"""
private const val ORDER_BY = """ORDER BY addedDate DESC"""
}
private val selective by lazy { AnnouncementDaoSelective(App.db) }
@RawQuery(observedEntities = [Announcement::class])
abstract override fun getRaw(query: SupportSQLiteQuery): LiveData<List<AnnouncementFull>>
@RawQuery(observedEntities = [Announcement::class])
abstract override fun getOne(query: SupportSQLiteQuery): LiveData<AnnouncementFull?>
// SELECTIVE UPDATE
@UpdateSelective(primaryKeys = ["profileId", "announcementId"], skippedColumns = ["addedDate", "announcementText"])
override fun update(item: Announcement) = selective.update(item)
override fun updateAll(items: List<Announcement>) = selective.updateAll(items)
// CLEAR
@Query("DELETE FROM announcements WHERE profileId = :profileId")
abstract override fun clear(profileId: Int)
// REMOVE NOT KEPT
@Query("DELETE FROM announcements WHERE keep = 0")
abstract override fun removeNotKept()
// GET ALL - LIVE DATA
fun getAll(profileId: Int) =
getRaw("$QUERY WHERE announcements.profileId = $profileId $ORDER_BY")
// GET ALL - NOW
fun getAllNow(profileId: Int) =
getRawNow("$QUERY WHERE announcements.profileId = $profileId $ORDER_BY")
fun getNotNotifiedNow() =
getRawNow("$QUERY WHERE notified = 0 $ORDER_BY")
fun getNotNotifiedNow(profileId: Int) =
getRawNow("$QUERY WHERE announcements.profileId = $profileId AND notified = 0 $ORDER_BY")
// GET ONE - NOW
fun getByIdNow(profileId: Int, id: Long) =
getOneNow("$QUERY WHERE announcements.profileId = $profileId AND announcementId = $id")
}

View File

@ -1,108 +0,0 @@
/*
* Copyright (c) Kacper Ziubryniewicz 2020-1-6
*/
package pl.szczodrzynski.edziennik.data.db.dao;
import androidx.lifecycle.LiveData;
import androidx.room.Dao;
import androidx.room.Insert;
import androidx.room.OnConflictStrategy;
import androidx.room.Query;
import androidx.room.RawQuery;
import androidx.sqlite.db.SimpleSQLiteQuery;
import androidx.sqlite.db.SupportSQLiteQuery;
import java.util.List;
import pl.szczodrzynski.edziennik.data.db.entity.Attendance;
import pl.szczodrzynski.edziennik.data.db.full.AttendanceFull;
import pl.szczodrzynski.edziennik.utils.models.Date;
import static pl.szczodrzynski.edziennik.data.db.entity.Metadata.TYPE_ATTENDANCE;
@Dao
public abstract class AttendanceDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
public abstract long add(Attendance attendance);
@Insert(onConflict = OnConflictStrategy.REPLACE)
public abstract void addAll(List<Attendance> attendanceList);
@Query("DELETE FROM attendances WHERE profileId = :profileId")
public abstract void clear(int profileId);
@Query("DELETE FROM attendances WHERE profileId = :profileId AND attendanceLessonDate > :date")
public abstract void clearAfterDate(int profileId, Date date);
@RawQuery(observedEntities = {Attendance.class})
abstract LiveData<List<AttendanceFull>> getAll(SupportSQLiteQuery query);
public LiveData<List<AttendanceFull>> getAll(int profileId, String filter) {
return getAll(new SimpleSQLiteQuery("SELECT \n" +
"*, \n" +
"teachers.teacherName || ' ' || teachers.teacherSurname AS teacherFullName\n" +
"FROM attendances \n" +
"LEFT JOIN teachers USING(profileId, teacherId)\n" +
"LEFT JOIN subjects USING(profileId, subjectId)\n" +
"LEFT JOIN metadata ON attendanceId = thingId AND thingType = " + TYPE_ATTENDANCE + " AND metadata.profileId = "+profileId+"\n" +
"WHERE attendances.profileId = "+profileId+" AND "+filter+"\n" +
"ORDER BY attendanceLessonDate DESC, attendanceStartTime DESC"));
}
public LiveData<List<AttendanceFull>> getAll(int profileId) {
return getAll(profileId, "1");
}
public LiveData<List<AttendanceFull>> getAllWhere(int profileId, String filter) {
return getAll(profileId, filter);
}
@RawQuery
abstract List<AttendanceFull> getAllNow(SupportSQLiteQuery query);
public List<AttendanceFull> getAllNow(int profileId, String filter) {
return getAllNow(new SimpleSQLiteQuery("SELECT \n" +
"*, \n" +
"teachers.teacherName || ' ' || teachers.teacherSurname AS teacherFullName\n" +
"FROM attendances \n" +
"LEFT JOIN teachers USING(profileId, teacherId)\n" +
"LEFT JOIN subjects USING(profileId, subjectId)\n" +
"LEFT JOIN metadata ON attendanceId = thingId AND thingType = " + TYPE_ATTENDANCE + " AND metadata.profileId = "+profileId+"\n" +
"WHERE attendances.profileId = "+profileId+" AND "+filter+"\n" +
"ORDER BY attendanceLessonDate DESC, attendanceStartTime DESC"));
}
public List<AttendanceFull> getNotNotifiedNow(int profileId) {
return getAllNow(profileId, "notified = 0");
}
@Query("SELECT * FROM attendances " +
"LEFT JOIN subjects USING(profileId, subjectId) " +
"LEFT JOIN metadata ON attendanceId = thingId AND thingType = " + TYPE_ATTENDANCE + " AND metadata.profileId = attendances.profileId " +
"WHERE notified = 0 " +
"ORDER BY attendanceLessonDate DESC, attendanceStartTime DESC")
public abstract List<AttendanceFull> getNotNotifiedNow();
// only absent and absent_excused count as absences
// all the other types are counted as being present
@Query("SELECT \n" +
"CAST(SUM(CASE WHEN attendanceType != "+Attendance.TYPE_ABSENT+" AND attendanceType != "+ Attendance.TYPE_ABSENT_EXCUSED+" THEN 1 ELSE 0 END) AS float)\n" +
" / \n" +
"CAST(count() AS float)*100 \n" +
"FROM attendances \n" +
"WHERE profileId = :profileId")
public abstract LiveData<Float> getAttendancePercentage(int profileId);
@Query("SELECT \n" +
"CAST(SUM(CASE WHEN attendanceType != "+Attendance.TYPE_ABSENT+" AND attendanceType != "+Attendance.TYPE_ABSENT_EXCUSED+" THEN 1 ELSE 0 END) AS float)\n" +
" / \n" +
"CAST(count() AS float)*100 \n" +
"FROM attendances \n" +
"WHERE profileId = :profileId AND attendanceSemester = :semester")
public abstract float getAttendancePercentageNow(int profileId, int semester);
@Query("SELECT \n" +
"CAST(SUM(CASE WHEN attendanceType != "+Attendance.TYPE_ABSENT+" AND attendanceType != "+Attendance.TYPE_ABSENT_EXCUSED+" THEN 1 ELSE 0 END) AS float)\n" +
" / \n" +
"CAST(count() AS float)*100 \n" +
"FROM attendances \n" +
"WHERE profileId = :profileId")
public abstract float getAttendancePercentageNow(int profileId);
}

View File

@ -0,0 +1,74 @@
/*
* Copyright (c) Kuba Szczodrzyński 2020-4-24.
*/
package pl.szczodrzynski.edziennik.data.db.dao
import androidx.lifecycle.LiveData
import androidx.room.Dao
import androidx.room.Query
import androidx.room.RawQuery
import androidx.sqlite.db.SupportSQLiteQuery
import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.annotation.SelectiveDao
import pl.szczodrzynski.edziennik.annotation.UpdateSelective
import pl.szczodrzynski.edziennik.data.db.AppDb
import pl.szczodrzynski.edziennik.data.db.entity.Attendance
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.full.AttendanceFull
import pl.szczodrzynski.edziennik.utils.models.Date
@Dao
@SelectiveDao(db = AppDb::class)
abstract class AttendanceDao : BaseDao<Attendance, AttendanceFull> {
companion object {
private const val QUERY = """
SELECT
*,
teachers.teacherName ||" "|| teachers.teacherSurname AS teacherName
FROM attendances
LEFT JOIN teachers USING(profileId, teacherId)
LEFT JOIN subjects USING(profileId, subjectId)
LEFT JOIN metadata ON attendanceId = thingId AND thingType = ${Metadata.TYPE_ATTENDANCE} AND metadata.profileId = attendances.profileId
"""
private const val ORDER_BY = """ORDER BY attendanceDate DESC, attendanceTime DESC"""
}
private val selective by lazy { AttendanceDaoSelective(App.db) }
@RawQuery(observedEntities = [Attendance::class])
abstract override fun getRaw(query: SupportSQLiteQuery): LiveData<List<AttendanceFull>>
@RawQuery(observedEntities = [Attendance::class])
abstract override fun getOne(query: SupportSQLiteQuery): LiveData<AttendanceFull?>
// SELECTIVE UPDATE
@UpdateSelective(primaryKeys = ["profileId", "attendanceId"], skippedColumns = ["addedDate", "announcementText"])
override fun update(item: Attendance) = selective.update(item)
override fun updateAll(items: List<Attendance>) = selective.updateAll(items)
// CLEAR
@Query("DELETE FROM attendances WHERE profileId = :profileId")
abstract override fun clear(profileId: Int)
// REMOVE NOT KEPT
@Query("DELETE FROM attendances WHERE keep = 0")
abstract override fun removeNotKept()
// GET ALL - LIVE DATA
fun getAll(profileId: Int) =
getRaw("$QUERY WHERE attendances.profileId = $profileId $ORDER_BY")
// GET ALL - NOW
fun getAllNow(profileId: Int) =
getRawNow("$QUERY WHERE attendances.profileId = $profileId $ORDER_BY")
fun getNotNotifiedNow() =
getRawNow("$QUERY WHERE notified = 0 $ORDER_BY")
fun getNotNotifiedNow(profileId: Int) =
getRawNow("$QUERY WHERE attendances.profileId = $profileId AND notified = 0 $ORDER_BY")
// GET ONE - NOW
fun getByIdNow(profileId: Int, id: Long) =
getOneNow("$QUERY WHERE attendances.profileId = $profileId AND attendanceId = $id")
@Query("UPDATE attendances SET keep = 0 WHERE profileId = :profileId AND attendanceDate > :date")
abstract fun dontKeepAfterDate(profileId: Int, date: Date?)
}

View File

@ -16,13 +16,15 @@ interface BaseDao<T : Keepable, F : T> {
fun getRaw(query: SupportSQLiteQuery): LiveData<List<F>>
fun getRaw(query: String) = getRaw(SimpleSQLiteQuery(query))
@RawQuery
fun getOne(query: SupportSQLiteQuery): LiveData<F?>
fun getOne(query: String) = getOne(SimpleSQLiteQuery(query))
@RawQuery
fun getRawNow(query: SupportSQLiteQuery): List<F>
fun getRawNow(query: String) = getRawNow(SimpleSQLiteQuery(query))
@RawQuery
fun getOneNow(query: SupportSQLiteQuery): F?
fun getOneNow(query: String) = getOneNow(SimpleSQLiteQuery(query))
@Query("DELETE FROM events WHERE keep = 0")
fun removeNotKept()
/**
@ -41,12 +43,14 @@ interface BaseDao<T : Keepable, F : T> {
/**
* REPLACE an [item] in the database,
* removing any conflicting rows.
* Creates the item if it does not exist yet.
*/
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun replace(item: T)
/**
* REPLACE [items] in the database,
* removing any conflicting rows.
* Creates items if it does not exist yet.
*/
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun replaceAll(items: List<T>)
@ -97,4 +101,21 @@ interface BaseDao<T : Keepable, F : T> {
if (removeNotKept) removeNotKept()
return insertResult
}
/**
* Make sure that [items] are in the database.
* When [forceReplace] == false, do a selective update (UPSERT).
* When [forceReplace] == true, add all items replacing any conflicting ones (REPLACE).
*
* @param forceReplace whether to replace all items instead of selectively updating
* @param removeNotKept whether to remove all items whose [keep] parameter is false
*/
fun putAll(items: List<T>, forceReplace: Boolean = false, removeNotKept: Boolean = false) {
if (items.isEmpty())
return
if (forceReplace)
replaceAll(items)
else
upsertAll(items)
}
}

View File

@ -31,8 +31,8 @@ abstract class EventDao : BaseDao<Event, EventFull> {
eventTypes.eventTypeName AS typeName,
eventTypes.eventTypeColor AS typeColor
FROM events
LEFT JOIN subjects USING(profileId, subjectId)
LEFT JOIN teachers USING(profileId, teacherId)
LEFT JOIN subjects USING(profileId, subjectId)
LEFT JOIN teams USING(profileId, teamId)
LEFT JOIN eventTypes USING(profileId, eventType)
LEFT JOIN metadata ON eventId = thingId AND (thingType = ${Metadata.TYPE_EVENT} OR thingType = ${Metadata.TYPE_HOMEWORK}) AND metadata.profileId = events.profileId
@ -47,6 +47,8 @@ abstract class EventDao : BaseDao<Event, EventFull> {
@RawQuery(observedEntities = [Event::class])
abstract override fun getRaw(query: SupportSQLiteQuery): LiveData<List<EventFull>>
@RawQuery(observedEntities = [Event::class])
abstract override fun getOne(query: SupportSQLiteQuery): LiveData<EventFull?>
// SELECTIVE UPDATE
@UpdateSelective(primaryKeys = ["profileId", "eventId"], skippedColumns = ["eventIsDone", "eventBlacklisted", "homeworkBody", "attachmentIds", "attachmentNames"])
@ -56,6 +58,9 @@ abstract class EventDao : BaseDao<Event, EventFull> {
// CLEAR
@Query("DELETE FROM events WHERE profileId = :profileId")
abstract override fun clear(profileId: Int)
// REMOVE NOT KEPT
@Query("DELETE FROM events WHERE keep = 0")
abstract override fun removeNotKept()
// GET ALL - LIVE DATA
fun getAll(profileId: Int) =

View File

@ -1,32 +1,86 @@
/*
* Copyright (c) Kacper Ziubryniewicz 2020-1-6
* Copyright (c) Kuba Szczodrzyński 2020-4-24.
*/
package pl.szczodrzynski.edziennik.data.db.dao
import androidx.lifecycle.LiveData
import androidx.room.*
import androidx.sqlite.db.SimpleSQLiteQuery
import androidx.room.Dao
import androidx.room.Query
import androidx.room.RawQuery
import androidx.room.Transaction
import androidx.sqlite.db.SupportSQLiteQuery
import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.annotation.SelectiveDao
import pl.szczodrzynski.edziennik.annotation.UpdateSelective
import pl.szczodrzynski.edziennik.data.db.AppDb
import pl.szczodrzynski.edziennik.data.db.entity.Grade
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.full.GradeFull
import pl.szczodrzynski.edziennik.utils.models.Date
import java.util.*
import kotlin.collections.List
import kotlin.collections.component1
import kotlin.collections.component2
import kotlin.collections.iterator
import kotlin.collections.set
@Dao
abstract class GradeDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
abstract fun add(grade: Grade): Long
@SelectiveDao(db = AppDb::class)
abstract class GradeDao : BaseDao<Grade, GradeFull> {
companion object {
private const val QUERY = """
SELECT
*,
teachers.teacherName ||" "|| teachers.teacherSurname AS teacherName
FROM grades
LEFT JOIN teachers USING(profileId, teacherId)
LEFT JOIN subjects USING(profileId, subjectId)
LEFT JOIN metadata ON gradeId = thingId AND thingType = ${Metadata.TYPE_GRADE} AND metadata.profileId = grades.profileId
"""
@Insert(onConflict = OnConflictStrategy.REPLACE)
abstract fun addAll(gradeList: List<Grade>)
private const val ORDER_BY = """ORDER BY addedDate DESC"""
}
private val selective by lazy { GradeDaoSelective(App.db) }
@RawQuery(observedEntities = [Grade::class])
abstract override fun getRaw(query: SupportSQLiteQuery): LiveData<List<GradeFull>>
@RawQuery(observedEntities = [Grade::class])
abstract override fun getOne(query: SupportSQLiteQuery): LiveData<GradeFull?>
// SELECTIVE UPDATE
@UpdateSelective(primaryKeys = ["profileId", "gradeId"], skippedColumns = ["addedDate", "gradeClassAverage"])
override fun update(item: Grade) = selective.update(item)
override fun updateAll(items: List<Grade>) = selective.updateAll(items)
// CLEAR
@Query("DELETE FROM grades WHERE profileId = :profileId")
abstract fun clear(profileId: Int)
abstract override fun clear(profileId: Int)
// REMOVE NOT KEPT
@Query("DELETE FROM grades WHERE keep = 0")
abstract override fun removeNotKept()
// GET ALL - LIVE DATA
fun getAll(profileId: Int) =
getRaw("$QUERY WHERE grades.profileId = $profileId $ORDER_BY")
fun getAllFromDate(profileId: Int, date: Date) =
getRaw("$QUERY WHERE grades.profileId = $profileId AND addedDate > ${date.inMillis} $ORDER_BY")
fun getAllBySubject(profileId: Int, subjectId: Long) =
getRaw("$QUERY WHERE grades.profileId = $profileId AND subjectId = $subjectId $ORDER_BY")
fun getAllOrderBy(profileId: Int, orderBy: String) =
getRaw("$QUERY WHERE grades.profileId = $profileId ORDER BY $orderBy")
// GET ALL - NOW
fun getAllNow(profileId: Int) =
getRawNow("$QUERY WHERE grades.profileId = $profileId $ORDER_BY")
fun getNotNotifiedNow() =
getRawNow("$QUERY WHERE notified = 0 $ORDER_BY")
fun getNotNotifiedNow(profileId: Int) =
getRawNow("$QUERY WHERE grades.profileId = $profileId AND notified = 0 $ORDER_BY")
fun getByParentIdNow(profileId: Int, parentId: Long) =
getRawNow("$QUERY WHERE grades.profileId = $profileId AND gradeParentId = $parentId $ORDER_BY")
// GET ONE - NOW
fun getByIdNow(profileId: Int, id: Long) =
getOneNow("$QUERY WHERE grades.profileId = $profileId AND gradeId = $id")
@Query("DELETE FROM grades WHERE profileId = :profileId AND gradeType = :type")
abstract fun clearWithType(profileId: Int, type: Int)
@ -37,66 +91,13 @@ abstract class GradeDao {
@Query("DELETE FROM grades WHERE profileId = :profileId AND gradeSemester = :semester AND gradeType = :type")
abstract fun clearForSemesterWithType(profileId: Int, semester: Int, type: Int)
@RawQuery(observedEntities = [Grade::class])
abstract fun getAll(query: SupportSQLiteQuery?): LiveData<List<GradeFull>>
fun getAll(profileId: Int, filter: String, orderBy: String): LiveData<List<GradeFull>> {
return getAll(SimpleSQLiteQuery("SELECT \n" +
"*, \n" +
"teachers.teacherName || ' ' || teachers.teacherSurname AS teacherFullName\n" +
"FROM grades \n" +
"LEFT JOIN subjects USING(profileId, subjectId)\n" +
"LEFT JOIN teachers USING(profileId, teacherId)\n" +
"LEFT JOIN metadata ON gradeId = thingId AND thingType = " + Metadata.TYPE_GRADE + " AND metadata.profileId = " + profileId + "\n" +
"WHERE grades.profileId = " + profileId + " AND " + filter + "\n" +
"ORDER BY " + orderBy)) // TODO: 2019-04-30 why did I add sorting by gradeType???
}
fun getAllOrderBy(profileId: Int, orderBy: String): LiveData<List<GradeFull>> {
return getAll(profileId, "1", orderBy)
}
fun getAllWhere(profileId: Int, filter: String): LiveData<List<GradeFull>> {
return getAll(profileId, filter, "addedDate DESC")
}
@RawQuery
abstract fun getAllNow(query: SupportSQLiteQuery?): List<GradeFull>
fun getAllNow(profileId: Int, filter: String): List<GradeFull> {
return getAllNow(SimpleSQLiteQuery("SELECT \n" +
"*, \n" +
"teachers.teacherName || ' ' || teachers.teacherSurname AS teacherFullName\n" +
"FROM grades \n" +
"LEFT JOIN subjects USING(profileId, subjectId)\n" +
"LEFT JOIN teachers USING(profileId, teacherId)\n" +
"LEFT JOIN metadata ON gradeId = thingId AND thingType = " + Metadata.TYPE_GRADE + " AND metadata.profileId = " + profileId + "\n" +
"WHERE grades.profileId = " + profileId + " AND " + filter + "\n" +
"ORDER BY addedDate DESC"))
}
fun getNotNotifiedNow(profileId: Int): List<GradeFull> {
return getAllNow(profileId, "notified = 0")
}
fun getAllWithParentIdNow(profileId: Int, parentId: Long): List<GradeFull> {
return getAllNow(profileId, "gradeParentId = $parentId")
}
@get:Query("SELECT * FROM grades " +
"LEFT JOIN subjects USING(profileId, subjectId) " +
"LEFT JOIN metadata ON gradeId = thingId AND thingType = " + Metadata.TYPE_GRADE + " AND metadata.profileId = grades.profileId " +
"WHERE notified = 0 " +
"ORDER BY addedDate DESC")
abstract val notNotifiedNow: List<GradeFull>
@RawQuery
abstract fun getNow(query: SupportSQLiteQuery): GradeFull?
// GRADE DETAILS - MOBIDZIENNIK
@Query("UPDATE grades SET gradeClassAverage = :classAverage, gradeColor = :color WHERE profileId = :profileId AND gradeId = :gradeId")
abstract fun updateDetailsById(profileId: Int, gradeId: Long, classAverage: Float, color: Int)
@Query("UPDATE metadata SET addedDate = :addedDate WHERE profileId = :profileId AND thingType = " + Metadata.TYPE_GRADE + " AND thingId = :gradeId")
@Query("UPDATE grades SET addedDate = :addedDate WHERE profileId = :profileId AND gradeId = :gradeId")
abstract fun updateAddedDateById(profileId: Int, gradeId: Long, addedDate: Long)
@Transaction
@ -118,7 +119,7 @@ abstract class GradeDao {
@Query("SELECT gradeColor FROM grades WHERE profileId = :profileId ORDER BY gradeId")
abstract fun getColors(profileId: Int): List<Int>
@Query("SELECT addedDate FROM metadata WHERE profileId = :profileId AND thingType = " + Metadata.TYPE_GRADE + " ORDER BY thingId")
@Query("SELECT addedDate FROM grades WHERE profileId = :profileId ORDER BY gradeId")
abstract fun getAddedDates(profileId: Int): List<Long>
@Transaction
@ -134,8 +135,4 @@ abstract class GradeDao {
gradeAddedDates[gradeId] = addedDates.next()
}
}
fun getAllFromDate(profileId: Int, date: Long): LiveData<List<GradeFull>> {
return getAllWhere(profileId, "addedDate > $date")
}
}

View File

@ -1,87 +0,0 @@
/*
* Copyright (c) Kacper Ziubryniewicz 2020-1-6
*/
package pl.szczodrzynski.edziennik.data.db.dao;
import androidx.annotation.Nullable;
import androidx.lifecycle.LiveData;
import androidx.room.Dao;
import androidx.room.Insert;
import androidx.room.OnConflictStrategy;
import androidx.room.Query;
import androidx.room.RawQuery;
import androidx.sqlite.db.SimpleSQLiteQuery;
import androidx.sqlite.db.SupportSQLiteQuery;
import java.util.List;
import pl.szczodrzynski.edziennik.data.db.entity.LuckyNumber;
import pl.szczodrzynski.edziennik.data.db.entity.Metadata;
import pl.szczodrzynski.edziennik.data.db.entity.Notice;
import pl.szczodrzynski.edziennik.data.db.full.LuckyNumberFull;
import pl.szczodrzynski.edziennik.utils.models.Date;
import static pl.szczodrzynski.edziennik.data.db.entity.Metadata.TYPE_LUCKY_NUMBER;
@Dao
public abstract class LuckyNumberDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
public abstract void add(LuckyNumber luckyNumber);
@Insert(onConflict = OnConflictStrategy.REPLACE)
public abstract void addAll(List<LuckyNumber> luckyNumberList);
@Query("DELETE FROM luckyNumbers WHERE profileId = :profileId")
public abstract void clear(int profileId);
@Query("SELECT * FROM luckyNumbers WHERE profileId = :profileId AND luckyNumberDate = :date")
public abstract LiveData<LuckyNumber> getByDate(int profileId, Date date);
@Query("SELECT * FROM luckyNumbers WHERE profileId = :profileId AND luckyNumberDate = :date")
public abstract LuckyNumber getByDateNow(int profileId, Date date);
@Nullable
@Query("SELECT * FROM luckyNumbers WHERE profileId = :profileId AND luckyNumberDate >= :date ORDER BY luckyNumberDate DESC LIMIT 1")
public abstract LuckyNumber getNearestFutureNow(int profileId, int date);
@Query("SELECT * FROM luckyNumbers WHERE profileId = :profileId AND luckyNumberDate >= :date ORDER BY luckyNumberDate DESC LIMIT 1")
public abstract LiveData<LuckyNumber> getNearestFuture(int profileId, int date);
@RawQuery(observedEntities = {LuckyNumber.class})
abstract LiveData<List<LuckyNumberFull>> getAll(SupportSQLiteQuery query);
public LiveData<List<LuckyNumberFull>> getAll(int profileId, String filter) {
return getAll(new SimpleSQLiteQuery("SELECT\n" +
"*\n" +
"FROM luckyNumbers\n" +
"LEFT JOIN metadata ON luckyNumberDate = thingId AND thingType = "+TYPE_LUCKY_NUMBER+" AND metadata.profileId = "+profileId+"\n" +
"WHERE luckyNumbers.profileId = "+profileId+" AND "+filter+"\n" +
"ORDER BY addedDate DESC"));
}
public LiveData<List<LuckyNumberFull>> getAll(int profileId) {
return getAll(profileId, "1");
}
public LiveData<List<LuckyNumberFull>> getAllWhere(int profileId, String filter) {
return getAll(profileId, filter);
}
@RawQuery(observedEntities = {Notice.class, Metadata.class})
abstract List<LuckyNumberFull> getAllNow(SupportSQLiteQuery query);
public List<LuckyNumberFull> getAllNow(int profileId, String filter) {
return getAllNow(new SimpleSQLiteQuery("SELECT\n" +
"*\n" +
"FROM luckyNumbers\n" +
"LEFT JOIN metadata ON luckyNumberDate = thingId AND thingType = "+TYPE_LUCKY_NUMBER+" AND metadata.profileId = "+profileId+"\n" +
"WHERE luckyNumbers.profileId = "+profileId+" AND "+filter+"\n" +
"ORDER BY addedDate DESC"));
}
public List<LuckyNumberFull> getNotNotifiedNow(int profileId) {
return getAllNow(profileId, "notified = 0");
}
@Query("SELECT * FROM luckyNumbers\n" +
"LEFT JOIN metadata ON luckyNumberDate = thingId AND thingType = "+TYPE_LUCKY_NUMBER+" AND metadata.profileId = luckyNumbers.profileId " +
"WHERE notified = 0 " +
"ORDER BY addedDate DESC")
public abstract List<LuckyNumberFull> getNotNotifiedNow();
}

View File

@ -0,0 +1,74 @@
/*
* Copyright (c) Kuba Szczodrzyński 2020-4-25.
*/
package pl.szczodrzynski.edziennik.data.db.dao
import androidx.lifecycle.LiveData
import androidx.room.Dao
import androidx.room.Query
import androidx.room.RawQuery
import androidx.sqlite.db.SupportSQLiteQuery
import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.annotation.SelectiveDao
import pl.szczodrzynski.edziennik.annotation.UpdateSelective
import pl.szczodrzynski.edziennik.data.db.AppDb
import pl.szczodrzynski.edziennik.data.db.entity.LuckyNumber
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.full.LuckyNumberFull
import pl.szczodrzynski.edziennik.utils.models.Date
@Dao
@SelectiveDao(db = AppDb::class)
abstract class LuckyNumberDao : BaseDao<LuckyNumber, LuckyNumberFull> {
companion object {
private const val QUERY = """
SELECT
*
FROM luckyNumbers
LEFT JOIN metadata ON luckyNumberDate = thingId AND thingType = ${Metadata.TYPE_LUCKY_NUMBER} AND metadata.profileId = luckyNumbers.profileId
"""
private const val ORDER_BY = """ORDER BY luckyNumberDate DESC"""
}
private val selective by lazy { LuckyNumberDaoSelective(App.db) }
@RawQuery(observedEntities = [LuckyNumber::class])
abstract override fun getRaw(query: SupportSQLiteQuery): LiveData<List<LuckyNumberFull>>
@RawQuery(observedEntities = [LuckyNumber::class])
abstract override fun getOne(query: SupportSQLiteQuery): LiveData<LuckyNumberFull?>
// SELECTIVE UPDATE
@UpdateSelective(primaryKeys = ["profileId", "luckyNumberDate"], skippedColumns = ["addedDate"])
override fun update(item: LuckyNumber) = selective.update(item)
override fun updateAll(items: List<LuckyNumber>) = selective.updateAll(items)
// CLEAR
@Query("DELETE FROM luckyNumbers WHERE profileId = :profileId")
abstract override fun clear(profileId: Int)
// REMOVE NOT KEPT
@Query("DELETE FROM luckyNumbers WHERE keep = 0")
abstract override fun removeNotKept()
// GET ALL - LIVE DATA
fun getAll(profileId: Int) =
getRaw("$QUERY WHERE luckyNumbers.profileId = $profileId $ORDER_BY")
// GET ALL - NOW
fun getAllNow(profileId: Int) =
getRawNow("$QUERY WHERE luckyNumbers.profileId = $profileId $ORDER_BY")
fun getNotNotifiedNow() =
getRawNow("$QUERY WHERE notified = 0 $ORDER_BY")
fun getNotNotifiedNow(profileId: Int) =
getRawNow("$QUERY WHERE luckyNumbers.profileId = $profileId AND notified = 0 $ORDER_BY")
// GET ONE - LIVE DATA
fun getNearestFuture(profileId: Int, today: Date) =
getOne("$QUERY WHERE luckyNumbers.profileId = $profileId AND luckyNumberDate >= ${today.value} $ORDER_BY LIMIT 1")
// GET ONE - NOW
fun getByIdNow(profileId: Int, id: Long) =
getOneNow("$QUERY WHERE attendances.profileId = $profileId AND attendanceId = $id")
fun getNearestFutureNow(profileId: Int, today: Date) =
getOneNow("$QUERY WHERE luckyNumbers.profileId = $profileId AND luckyNumberDate >= ${today.value} $ORDER_BY LIMIT 1")
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) Kacper Ziubryniewicz 2020-1-6
* Copyright (c) Kuba Szczodrzyński 2020-4-25.
*/
package pl.szczodrzynski.edziennik.data.db.dao
@ -36,7 +36,10 @@ abstract class MessageDao : BaseDao<Message, MessageFull> {
@RawQuery(observedEntities = [Message::class])
abstract override fun getRaw(query: SupportSQLiteQuery): LiveData<List<MessageFull>>
@RawQuery(observedEntities = [Message::class])
abstract override fun getOne(query: SupportSQLiteQuery): LiveData<MessageFull?>
// SELECTIVE UPDATE
@UpdateSelective(primaryKeys = ["profileId", "messageId"], skippedColumns = ["messageType", "messageBody", "messageIsPinned", "attachmentIds", "attachmentNames", "attachmentSizes"])
override fun update(item: Message) = selective.update(item)
override fun updateAll(items: List<Message>) = selective.updateAll(items)
@ -44,6 +47,9 @@ abstract class MessageDao : BaseDao<Message, MessageFull> {
// CLEAR
@Query("DELETE FROM messages WHERE profileId = :profileId")
abstract override fun clear(profileId: Int)
// REMOVE NOT KEPT
@Query("DELETE FROM messages WHERE keep = 0")
abstract override fun removeNotKept()
// GET ALL - LIVE DATA
fun getAll(profileId: Int) =
@ -64,4 +70,6 @@ abstract class MessageDao : BaseDao<Message, MessageFull> {
// GET ONE - NOW
fun getByIdNow(profileId: Int, id: Long) =
getOneNow("$QUERY WHERE messages.profileId = $profileId AND messageId = $id")
}

View File

@ -63,37 +63,37 @@ public abstract class MetadataDao {
@Transaction
public void setSeen(int profileId, Object o, boolean seen) {
if (o instanceof Grade) {
if (add(new Metadata(profileId, TYPE_GRADE, ((Grade) o).getId(), seen, false, 0)) == -1) {
if (add(new Metadata(profileId, TYPE_GRADE, ((Grade) o).getId(), seen, false)) == -1) {
updateSeen(profileId, TYPE_GRADE, ((Grade) o).getId(), seen);
}
}
if (o instanceof Attendance) {
if (add(new Metadata(profileId, TYPE_ATTENDANCE, ((Attendance) o).id, seen, false, 0)) == -1) {
updateSeen(profileId, TYPE_ATTENDANCE, ((Attendance) o).id, seen);
if (add(new Metadata(profileId, TYPE_ATTENDANCE, ((Attendance) o).getId(), seen, false)) == -1) {
updateSeen(profileId, TYPE_ATTENDANCE, ((Attendance) o).getId(), seen);
}
}
if (o instanceof Notice) {
if (add(new Metadata(profileId, TYPE_NOTICE, ((Notice) o).id, seen, false, 0)) == -1) {
updateSeen(profileId, TYPE_NOTICE, ((Notice) o).id, seen);
if (add(new Metadata(profileId, TYPE_NOTICE, ((Notice) o).getId(), seen, false)) == -1) {
updateSeen(profileId, TYPE_NOTICE, ((Notice) o).getId(), seen);
}
}
if (o instanceof Event) {
if (add(new Metadata(profileId, ((Event) o).getType() == Event.TYPE_HOMEWORK ? TYPE_HOMEWORK : TYPE_EVENT, ((Event) o).getId(), seen, false, 0)) == -1) {
if (add(new Metadata(profileId, ((Event) o).getType() == Event.TYPE_HOMEWORK ? TYPE_HOMEWORK : TYPE_EVENT, ((Event) o).getId(), seen, false)) == -1) {
updateSeen(profileId, ((Event) o).getType() == Event.TYPE_HOMEWORK ? TYPE_HOMEWORK : TYPE_EVENT, ((Event) o).getId(), seen);
}
}
if (o instanceof LessonFull) {
if (add(new Metadata(profileId, TYPE_LESSON_CHANGE, ((LessonFull) o).getId(), seen, false, 0)) == -1) {
if (add(new Metadata(profileId, TYPE_LESSON_CHANGE, ((LessonFull) o).getId(), seen, false)) == -1) {
updateSeen(profileId, TYPE_LESSON_CHANGE, ((LessonFull) o).getId(), seen);
}
}
if (o instanceof Announcement) {
if (add(new Metadata(profileId, TYPE_ANNOUNCEMENT, ((Announcement) o).id, seen, false, 0)) == -1) {
updateSeen(profileId, TYPE_ANNOUNCEMENT, ((Announcement) o).id, seen);
if (add(new Metadata(profileId, TYPE_ANNOUNCEMENT, ((Announcement) o).getId(), seen, false)) == -1) {
updateSeen(profileId, TYPE_ANNOUNCEMENT, ((Announcement) o).getId(), seen);
}
}
if (o instanceof Message) {
if (add(new Metadata(profileId, TYPE_MESSAGE, ((Message) o).getId(), seen, false, 0)) == -1) {
if (add(new Metadata(profileId, TYPE_MESSAGE, ((Message) o).getId(), seen, false)) == -1) {
updateSeen(profileId, TYPE_MESSAGE, ((Message) o).getId(), seen);
}
}
@ -102,37 +102,37 @@ public abstract class MetadataDao {
@Transaction
public void setNotified(int profileId, Object o, boolean notified) {
if (o instanceof Grade) {
if (add(new Metadata(profileId, TYPE_GRADE, ((Grade) o).getId(), false, notified, 0)) == -1) {
if (add(new Metadata(profileId, TYPE_GRADE, ((Grade) o).getId(), false, notified)) == -1) {
updateNotified(profileId, TYPE_GRADE, ((Grade) o).getId(), notified);
}
}
if (o instanceof Attendance) {
if (add(new Metadata(profileId, TYPE_ATTENDANCE, ((Attendance) o).id, false, notified, 0)) == -1) {
updateNotified(profileId, TYPE_ATTENDANCE, ((Attendance) o).id, notified);
if (add(new Metadata(profileId, TYPE_ATTENDANCE, ((Attendance) o).getId(), false, notified)) == -1) {
updateNotified(profileId, TYPE_ATTENDANCE, ((Attendance) o).getId(), notified);
}
}
if (o instanceof Notice) {
if (add(new Metadata(profileId, TYPE_NOTICE, ((Notice) o).id, false, notified, 0)) == -1) {
updateNotified(profileId, TYPE_NOTICE, ((Notice) o).id, notified);
if (add(new Metadata(profileId, TYPE_NOTICE, ((Notice) o).getId(), false, notified)) == -1) {
updateNotified(profileId, TYPE_NOTICE, ((Notice) o).getId(), notified);
}
}
if (o instanceof Event) {
if (add(new Metadata(profileId, ((Event) o).getType() == Event.TYPE_HOMEWORK ? TYPE_HOMEWORK : TYPE_EVENT, ((Event) o).getId(), false, notified, 0)) == -1) {
if (add(new Metadata(profileId, ((Event) o).getType() == Event.TYPE_HOMEWORK ? TYPE_HOMEWORK : TYPE_EVENT, ((Event) o).getId(), false, notified)) == -1) {
updateNotified(profileId, ((Event) o).getType() == Event.TYPE_HOMEWORK ? TYPE_HOMEWORK : TYPE_EVENT, ((Event) o).getId(), notified);
}
}
if (o instanceof LessonFull) {
if (add(new Metadata(profileId, TYPE_LESSON_CHANGE, ((LessonFull) o).getId(), false, notified, 0)) == -1) {
if (add(new Metadata(profileId, TYPE_LESSON_CHANGE, ((LessonFull) o).getId(), false, notified)) == -1) {
updateNotified(profileId, TYPE_LESSON_CHANGE, ((LessonFull) o).getId(), notified);
}
}
if (o instanceof Announcement) {
if (add(new Metadata(profileId, TYPE_ANNOUNCEMENT, ((Announcement) o).id, false, notified, 0)) == -1) {
updateNotified(profileId, TYPE_ANNOUNCEMENT, ((Announcement) o).id, notified);
if (add(new Metadata(profileId, TYPE_ANNOUNCEMENT, ((Announcement) o).getId(), false, notified)) == -1) {
updateNotified(profileId, TYPE_ANNOUNCEMENT, ((Announcement) o).getId(), notified);
}
}
if (o instanceof Message) {
if (add(new Metadata(profileId, TYPE_MESSAGE, ((Message) o).getId(), false, notified, 0)) == -1) {
if (add(new Metadata(profileId, TYPE_MESSAGE, ((Message) o).getId(), false, notified)) == -1) {
updateNotified(profileId, TYPE_MESSAGE, ((Message) o).getId(), notified);
}
}
@ -141,7 +141,7 @@ public abstract class MetadataDao {
@Transaction
public void setBoth(int profileId, Event o, boolean seen, boolean notified, long addedDate) {
if (o != null) {
if (add(new Metadata(profileId, o.getType() == Event.TYPE_HOMEWORK ? TYPE_HOMEWORK : TYPE_EVENT, o.getId(), seen, notified, addedDate)) == -1) {
if (add(new Metadata(profileId, o.getType() == Event.TYPE_HOMEWORK ? TYPE_HOMEWORK : TYPE_EVENT, o.getId(), seen, notified)) == -1) {
updateSeen(profileId, o.getType() == Event.TYPE_HOMEWORK ? TYPE_HOMEWORK : TYPE_EVENT, o.getId(), seen);
updateNotified(profileId, o.getType() == Event.TYPE_HOMEWORK ? TYPE_HOMEWORK : TYPE_EVENT, o.getId(), notified);
}

View File

@ -1,82 +0,0 @@
/*
* Copyright (c) Kacper Ziubryniewicz 2020-1-6
*/
package pl.szczodrzynski.edziennik.data.db.dao;
import androidx.lifecycle.LiveData;
import androidx.room.Dao;
import androidx.room.Insert;
import androidx.room.OnConflictStrategy;
import androidx.room.Query;
import androidx.room.RawQuery;
import androidx.sqlite.db.SimpleSQLiteQuery;
import androidx.sqlite.db.SupportSQLiteQuery;
import java.util.List;
import pl.szczodrzynski.edziennik.data.db.entity.Metadata;
import pl.szczodrzynski.edziennik.data.db.entity.Notice;
import pl.szczodrzynski.edziennik.data.db.full.NoticeFull;
import static pl.szczodrzynski.edziennik.data.db.entity.Metadata.TYPE_NOTICE;
@Dao
public abstract class NoticeDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
public abstract long add(Notice notice);
@Insert(onConflict = OnConflictStrategy.REPLACE)
public abstract void addAll(List<Notice> noticeList);
@Query("DELETE FROM notices WHERE profileId = :profileId")
public abstract void clear(int profileId);
@Query("DELETE FROM notices WHERE profileId = :profileId AND noticeSemester = :semester")
public abstract void clearForSemester(int profileId, int semester);
@RawQuery(observedEntities = {Notice.class})
abstract LiveData<List<NoticeFull>> getAll(SupportSQLiteQuery query);
public LiveData<List<NoticeFull>> getAll(int profileId, String filter) {
return getAll(new SimpleSQLiteQuery("SELECT \n" +
"*, \n" +
"teachers.teacherName || ' ' || teachers.teacherSurname AS teacherFullName\n" +
"FROM notices \n" +
"LEFT JOIN teachers USING(profileId, teacherId)\n" +
"LEFT JOIN metadata ON noticeId = thingId AND thingType = "+TYPE_NOTICE+" AND metadata.profileId = "+profileId+"\n" +
"WHERE notices.profileId = "+profileId+" AND "+filter+"\n" +
"ORDER BY addedDate DESC"));
}
public LiveData<List<NoticeFull>> getAll(int profileId) {
return getAll(profileId, "1");
}
public LiveData<List<NoticeFull>> getAllWhere(int profileId, String filter) {
return getAll(profileId, filter);
}
@RawQuery(observedEntities = {Notice.class, Metadata.class})
abstract List<NoticeFull> getAllNow(SupportSQLiteQuery query);
public List<NoticeFull> getAllNow(int profileId, String filter) {
return getAllNow(new SimpleSQLiteQuery("SELECT \n" +
"*, \n" +
"teachers.teacherName || ' ' || teachers.teacherSurname AS teacherFullName\n" +
"FROM notices \n" +
"LEFT JOIN teachers USING(profileId, teacherId)\n" +
"LEFT JOIN metadata ON noticeId = thingId AND thingType = "+TYPE_NOTICE+" AND metadata.profileId = "+profileId+"\n" +
"WHERE notices.profileId = "+profileId+" AND "+filter+"\n" +
"ORDER BY addedDate DESC"));
}
public List<NoticeFull> getNotNotifiedNow(int profileId) {
return getAllNow(profileId, "notified = 0");
}
@Query("SELECT " +
"*, " +
"teachers.teacherName || ' ' || teachers.teacherSurname AS teacherFullName " +
"FROM notices " +
"LEFT JOIN teachers USING(profileId, teacherId) " +
"LEFT JOIN metadata ON noticeId = thingId AND thingType = "+TYPE_NOTICE+" AND metadata.profileId = notices.profileId " +
"WHERE notified = 0 " +
"ORDER BY addedDate DESC")
public abstract List<NoticeFull> getNotNotifiedNow();
}

View File

@ -0,0 +1,72 @@
/*
* Copyright (c) Kuba Szczodrzyński 2020-4-25.
*/
package pl.szczodrzynski.edziennik.data.db.dao
import androidx.lifecycle.LiveData
import androidx.room.Dao
import androidx.room.Query
import androidx.room.RawQuery
import androidx.sqlite.db.SupportSQLiteQuery
import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.annotation.SelectiveDao
import pl.szczodrzynski.edziennik.annotation.UpdateSelective
import pl.szczodrzynski.edziennik.data.db.AppDb
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.entity.Notice
import pl.szczodrzynski.edziennik.data.db.full.NoticeFull
@Dao
@SelectiveDao(db = AppDb::class)
abstract class NoticeDao : BaseDao<Notice, NoticeFull> {
companion object {
private const val QUERY = """
SELECT
*,
teachers.teacherName ||" "|| teachers.teacherSurname AS teacherName
FROM notices
LEFT JOIN teachers USING(profileId, teacherId)
LEFT JOIN metadata ON noticeId = thingId AND thingType = ${Metadata.TYPE_NOTICE} AND metadata.profileId = notices.profileId
"""
private const val ORDER_BY = """ORDER BY addedDate DESC"""
}
private val selective by lazy { NoticeDaoSelective(App.db) }
@RawQuery(observedEntities = [Notice::class])
abstract override fun getRaw(query: SupportSQLiteQuery): LiveData<List<NoticeFull>>
@RawQuery(observedEntities = [Notice::class])
abstract override fun getOne(query: SupportSQLiteQuery): LiveData<NoticeFull?>
// SELECTIVE UPDATE
@UpdateSelective(primaryKeys = ["profileId", "noticeId"], skippedColumns = ["addedDate"])
override fun update(item: Notice) = selective.update(item)
override fun updateAll(items: List<Notice>) = selective.updateAll(items)
// CLEAR
@Query("DELETE FROM notices WHERE profileId = :profileId")
abstract override fun clear(profileId: Int)
// REMOVE NOT KEPT
@Query("DELETE FROM notices WHERE keep = 0")
abstract override fun removeNotKept()
// GET ALL - LIVE DATA
fun getAll(profileId: Int) =
getRaw("$QUERY WHERE notices.profileId = $profileId $ORDER_BY")
// GET ALL - NOW
fun getAllNow(profileId: Int) =
getRawNow("$QUERY WHERE notices.profileId = $profileId $ORDER_BY")
fun getNotNotifiedNow() =
getRawNow("$QUERY WHERE notified = 0 $ORDER_BY")
fun getNotNotifiedNow(profileId: Int) =
getRawNow("$QUERY WHERE notices.profileId = $profileId AND notified = 0 $ORDER_BY")
// GET ONE - NOW
fun getByIdNow(profileId: Int, id: Long) =
getOneNow("$QUERY WHERE notices.profileId = $profileId AND noticeId = $id")
@Query("UPDATE notices SET keep = 0 WHERE profileId = :profileId AND noticeSemester = :semester")
abstract fun dontKeepSemester(profileId: Int, semester: Int)
}

View File

@ -1,65 +1,74 @@
/*
* Copyright (c) Kacper Ziubryniewicz 2020-1-6
* Copyright (c) Kuba Szczodrzyński 2020-4-25.
*/
package pl.szczodrzynski.edziennik.data.db.dao
import androidx.lifecycle.LiveData
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import androidx.room.RawQuery
import androidx.sqlite.db.SupportSQLiteQuery
import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.annotation.SelectiveDao
import pl.szczodrzynski.edziennik.annotation.UpdateSelective
import pl.szczodrzynski.edziennik.data.db.AppDb
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.entity.TeacherAbsence
import pl.szczodrzynski.edziennik.data.db.full.TeacherAbsenceFull
import pl.szczodrzynski.edziennik.utils.models.Date
@Dao
interface TeacherAbsenceDao {
@SelectiveDao(db = AppDb::class)
abstract class TeacherAbsenceDao : BaseDao<TeacherAbsence, TeacherAbsenceFull> {
companion object {
private const val QUERY = """
SELECT
*,
teachers.teacherName ||" "|| teachers.teacherSurname AS teacherName
FROM teacherAbsence
LEFT JOIN teachers USING(profileId, teacherId)
LEFT JOIN metadata ON teacherAbsenceId = thingId AND thingType = ${Metadata.TYPE_TEACHER_ABSENCE} AND metadata.profileId = teacherAbsence.profileId
"""
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun add(teacherAbsence: TeacherAbsence)
private const val ORDER_BY = """ORDER BY teacherAbsenceDateFrom ASC"""
}
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun addAll(teacherAbsenceList: List<TeacherAbsence>)
private val selective by lazy { TeacherAbsenceDaoSelective(App.db) }
@Query("SELECT * FROM teacherAbsence WHERE profileId = :profileId")
fun getAll(profileId: Int): List<TeacherAbsence>
@RawQuery(observedEntities = [TeacherAbsence::class])
abstract override fun getRaw(query: SupportSQLiteQuery): LiveData<List<TeacherAbsenceFull>>
@RawQuery(observedEntities = [TeacherAbsence::class])
abstract override fun getOne(query: SupportSQLiteQuery): LiveData<TeacherAbsenceFull?>
@Query("SELECT *, teachers.teacherName || ' ' || teachers.teacherSurname as teacherFullName, " +
"metadata.seen, metadata.notified, metadata.addedDate FROM teacherAbsence " +
"LEFT JOIN teachers USING (profileId, teacherId) " +
"LEFT JOIN metadata ON teacherAbsenceId = thingId AND metadata.thingType = " + Metadata.TYPE_TEACHER_ABSENCE +
" AND metadata.profileId = :profileId WHERE teachers.profileId = :profileId")
fun getAllFullNow(profileId: Int): List<TeacherAbsenceFull>
@Query("SELECT *, teachers.teacherName || ' ' || teachers.teacherSurname as teacherFullName, " +
"metadata.seen, metadata.notified, metadata.addedDate FROM teacherAbsence " +
"LEFT JOIN teachers USING (profileId, teacherId) " +
"LEFT JOIN metadata ON teacherAbsenceId = thingId AND metadata.thingType = " + Metadata.TYPE_TEACHER_ABSENCE +
" AND metadata.profileId = :profileId WHERE teachers.profileId = :profileId " +
"AND :date BETWEEN teacherAbsenceDateFrom AND teacherAbsenceDateTo")
fun getAllByDateFull(profileId: Int, date: Date): LiveData<List<TeacherAbsenceFull>>
@Query("SELECT *, teachers.teacherName || ' ' || teachers.teacherSurname as teacherFullName, " +
"metadata.seen, metadata.notified, metadata.addedDate FROM teacherAbsence " +
"LEFT JOIN teachers USING (profileId, teacherId) " +
"LEFT JOIN metadata ON teacherAbsenceId = thingId AND metadata.thingType = " + Metadata.TYPE_TEACHER_ABSENCE +
" AND metadata.profileId = :profileId WHERE teachers.profileId = :profileId " +
"AND :date BETWEEN teacherAbsenceDateFrom AND teacherAbsenceDateTo")
fun getAllByDateNow(profileId: Int, date: Date): List<TeacherAbsenceFull>
@Query("""
SELECT *,
teachers.teacherName || ' ' || teachers.teacherSurname as teacherFullName
FROM teacherAbsence
LEFT JOIN teachers USING (profileId, teacherId)
LEFT JOIN metadata ON teacherAbsenceId = thingId AND metadata.thingType = ${Metadata.TYPE_TEACHER_ABSENCE}
AND teachers.profileId = metadata.profileId WHERE metadata.notified = 0
ORDER BY addedDate DESC
""")
fun getNotNotifiedNow(): List<TeacherAbsenceFull>
// SELECTIVE UPDATE
@UpdateSelective(primaryKeys = ["profileId", "teacherAbsenceId"], skippedColumns = ["addedDate"])
override fun update(item: TeacherAbsence) = selective.update(item)
override fun updateAll(items: List<TeacherAbsence>) = selective.updateAll(items)
// CLEAR
@Query("DELETE FROM teacherAbsence WHERE profileId = :profileId")
fun clear(profileId: Int)
abstract override fun clear(profileId: Int)
// REMOVE NOT KEPT
@Query("DELETE FROM teacherAbsence WHERE keep = 0")
abstract override fun removeNotKept()
// GET ALL - LIVE DATA
fun getAll(profileId: Int) =
getRaw("$QUERY WHERE teacherAbsence.profileId = $profileId $ORDER_BY")
fun getAllByDate(profileId: Int, date: Date) =
getRaw("$QUERY WHERE teacherAbsence.profileId = $profileId AND '${date.stringY_m_d}' BETWEEN teacherAbsenceDateFrom AND teacherAbsenceDateTo $ORDER_BY")
// GET ALL - NOW
fun getAllNow(profileId: Int) =
getRawNow("$QUERY WHERE teacherAbsence.profileId = $profileId $ORDER_BY")
fun getNotNotifiedNow() =
getRawNow("$QUERY WHERE notified = 0 $ORDER_BY")
fun getNotNotifiedNow(profileId: Int) =
getRawNow("$QUERY WHERE teacherAbsence.profileId = $profileId AND notified = 0 $ORDER_BY")
fun getAllByDateNow(profileId: Int, date: Date) =
getRawNow("$QUERY WHERE teacherAbsence.profileId = $profileId AND '${date.stringY_m_d}' BETWEEN teacherAbsenceDateFrom AND teacherAbsenceDateTo $ORDER_BY")
// GET ONE - NOW
fun getByIdNow(profileId: Int, id: Long) =
getOneNow("$QUERY WHERE teacherAbsence.profileId = $profileId AND teacherAbsenceId = $id")
}

View File

@ -1,20 +1,25 @@
/*
* Copyright (c) Kacper Ziubryniewicz 2020-1-6
* Copyright (c) Kuba Szczodrzyński 2020-4-25.
*/
package pl.szczodrzynski.edziennik.data.db.dao
import androidx.lifecycle.LiveData
import androidx.room.*
import androidx.sqlite.db.SimpleSQLiteQuery
import androidx.room.Dao
import androidx.room.Query
import androidx.room.RawQuery
import androidx.sqlite.db.SupportSQLiteQuery
import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.annotation.SelectiveDao
import pl.szczodrzynski.edziennik.annotation.UpdateSelective
import pl.szczodrzynski.edziennik.data.db.AppDb
import pl.szczodrzynski.edziennik.data.db.entity.Lesson
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.full.LessonFull
import pl.szczodrzynski.edziennik.utils.models.Date
@Dao
interface TimetableDao {
@SelectiveDao(db = AppDb::class)
abstract class TimetableDao : BaseDao<Lesson, LessonFull> {
companion object {
private const val QUERY = """
SELECT
@ -25,7 +30,7 @@ interface TimetableDao {
oldS.subjectLongName AS oldSubjectName,
oldT.teacherName ||" "|| oldT.teacherSurname AS oldTeacherName,
oldG.teamName AS oldTeamName,
metadata.seen, metadata.notified, metadata.addedDate
metadata.seen, metadata.notified
FROM timetable
LEFT JOIN subjects USING(profileId, subjectId)
LEFT JOIN teachers USING(profileId, teacherId)
@ -35,111 +40,77 @@ interface TimetableDao {
LEFT JOIN teams AS oldG ON timetable.profileId = oldG.profileId AND timetable.oldTeamId = oldG.teamId
LEFT JOIN metadata ON id = thingId AND thingType = ${Metadata.TYPE_LESSON_CHANGE} AND metadata.profileId = timetable.profileId
"""
private const val ORDER_BY = """ORDER BY profileId, id, type"""
private const val IS_CHANGED = """type != -1 AND type != 0"""
}
@Insert(onConflict = OnConflictStrategy.REPLACE)
operator fun plusAssign(lessonList: List<Lesson>)
@Query("DELETE FROM timetable WHERE profileId = :profileId")
fun clear(profileId: Int)
@Query("DELETE FROM timetable WHERE profileId = :profileId AND type != -1 AND ((type != 3 AND date >= :dateFrom) OR ((type = 3 OR type = 1) AND oldDate >= :dateFrom))")
fun clearFromDate(profileId: Int, dateFrom: Date)
@Query("DELETE FROM timetable WHERE profileId = :profileId AND type != -1 AND ((type != 3 AND date <= :dateTo) OR ((type = 3 OR type = 1) AND oldDate <= :dateTo))")
fun clearToDate(profileId: Int, dateTo: Date)
@Query("DELETE FROM timetable WHERE profileId = :profileId AND type != -1 AND ((type != 3 AND date >= :dateFrom AND date <= :dateTo) OR ((type = 3 OR type = 1) AND oldDate >= :dateFrom AND oldDate <= :dateTo))")
fun clearBetweenDates(profileId: Int, dateFrom: Date, dateTo: Date)
private val selective by lazy { TimetableDaoSelective(App.db) }
@RawQuery(observedEntities = [Lesson::class])
fun getRaw(query: SupportSQLiteQuery): LiveData<List<LessonFull>>
abstract override fun getRaw(query: SupportSQLiteQuery): LiveData<List<LessonFull>>
@RawQuery(observedEntities = [Lesson::class])
abstract override fun getOne(query: SupportSQLiteQuery): LiveData<LessonFull?>
@Query("""
$QUERY
WHERE timetable.profileId = :profileId AND type != -1 AND type != 0
ORDER BY id, type
""")
fun getAllChangesNow(profileId: Int): List<LessonFull>
// SELECTIVE UPDATE
@UpdateSelective(primaryKeys = ["profileId", "id"], skippedColumns = ["addedDate"])
override fun update(item: Lesson) = selective.update(item)
override fun updateAll(items: List<Lesson>) = selective.updateAll(items)
@Query("""
$QUERY
WHERE timetable.profileId = :profileId AND type != -1 AND type != 0 AND ((type != 3 AND date = :date) OR ((type = 3 OR type = 1) AND oldDate = :date))
ORDER BY id, type
""")
fun getChangesForDateNow(profileId: Int, date: Date): List<LessonFull>
// CLEAR
@Query("DELETE FROM timetable WHERE profileId = :profileId")
abstract override fun clear(profileId: Int)
// REMOVE NOT KEPT
@Query("DELETE FROM timetable WHERE keep = 0")
abstract override fun removeNotKept()
fun getForDate(profileId: Int, date: Date) = getRaw(SimpleSQLiteQuery("""
$QUERY
WHERE timetable.profileId = $profileId AND ((type != 3 AND date = "${date.stringY_m_d}") OR ((type = 3 OR type = 1) AND oldDate = "${date.stringY_m_d}"))
ORDER BY id, type
"""))
// GET ALL - LIVE DATA
fun getAll(profileId: Int) =
getRaw("$QUERY WHERE timetable.profileId = $profileId $ORDER_BY")
fun getAllForDate(profileId: Int, date: Date) =
getRaw("$QUERY WHERE timetable.profileId = $profileId AND ((type != 3 AND date = '${date.stringY_m_d}') OR ((type = 3 OR type = 1) AND oldDate = '${date.stringY_m_d}')) $ORDER_BY")
fun getNextWithSubject(profileId: Int, date: Date, subjectId: Long) =
getOne("$QUERY " +
"WHERE timetable.profileId = $profileId " +
"AND ((type != 3 AND date > '${date.stringY_m_d}') OR ((type = 3 OR type = 1) AND oldDate > '${date.stringY_m_d}')) " +
"AND timetable.subjectId = $subjectId " +
"LIMIT 1")
fun getNextWithSubjectAndTeam(profileId: Int, date: Date, subjectId: Long, teamId: Long) =
getOne("$QUERY " +
"WHERE timetable.profileId = $profileId " +
"AND ((type != 3 AND date > '${date.stringY_m_d}') OR ((type = 3 OR type = 1) AND oldDate > '${date.stringY_m_d}')) " +
"AND timetable.subjectId = $subjectId " +
"AND timetable.teamId = $teamId " +
"LIMIT 1")
fun getBetweenDates(dateFrom: Date, dateTo: Date) =
getRaw("$QUERY WHERE (type != 3 AND date >= '${dateFrom.stringY_m_d}' AND date <= '${dateTo.stringY_m_d}') OR ((type = 3 OR type = 1) AND oldDate >= '${dateFrom.stringY_m_d}' AND oldDate <= '${dateTo.stringY_m_d}') $ORDER_BY")
@Query("""
$QUERY
WHERE timetable.profileId = :profileId AND ((type != 3 AND date = :date) OR ((type = 3 OR type = 1) AND oldDate = :date))
ORDER BY id, type
""")
fun getForDateNow(profileId: Int, date: Date): List<LessonFull>
// GET ALL - NOW
fun getAllNow(profileId: Int) =
getRawNow("$QUERY WHERE timetable.profileId = $profileId $ORDER_BY")
fun getNotNotifiedNow() =
getRawNow("$QUERY WHERE notified = 0 AND timetable.type NOT IN (${Lesson.TYPE_NORMAL}, ${Lesson.TYPE_NO_LESSONS}, ${Lesson.TYPE_SHIFTED_SOURCE}) $ORDER_BY")
fun getNotNotifiedNow(profileId: Int) =
getRawNow("$QUERY WHERE timetable.profileId = $profileId AND notified = 0 AND timetable.type NOT IN (${Lesson.TYPE_NORMAL}, ${Lesson.TYPE_NO_LESSONS}, ${Lesson.TYPE_SHIFTED_SOURCE}) $ORDER_BY")
fun getAllForDateNow(profileId: Int, date: Date) =
getRawNow("$QUERY WHERE timetable.profileId = $profileId AND ((type != 3 AND date = '${date.stringY_m_d}') OR ((type = 3 OR type = 1) AND oldDate = '${date.stringY_m_d}')) $ORDER_BY")
fun getChangesNow(profileId: Int) =
getRawNow("$QUERY WHERE timetable.profileId = $profileId AND $IS_CHANGED $ORDER_BY")
fun getChangesForDateNow(profileId: Int, date: Date) =
getRawNow("$QUERY WHERE timetable.profileId = $profileId AND $IS_CHANGED AND ((type != 3 AND date = '${date.stringY_m_d}') OR ((type = 3 OR type = 1) AND oldDate = '${date.stringY_m_d}')) $ORDER_BY")
fun getBetweenDatesNow(dateFrom: Date, dateTo: Date) =
getRawNow("$QUERY WHERE (type != 3 AND date >= '${dateFrom.stringY_m_d}' AND date <= '${dateTo.stringY_m_d}') OR ((type = 3 OR type = 1) AND oldDate >= '${dateFrom.stringY_m_d}' AND oldDate <= '${dateTo.stringY_m_d}') $ORDER_BY")
@Query("""
$QUERY
WHERE timetable.profileId = :profileId AND ((type != 3 AND date > :today) OR ((type = 3 OR type = 1) AND oldDate > :today)) AND timetable.subjectId = :subjectId
ORDER BY id, type
LIMIT 1
""")
fun getNextWithSubject(profileId: Int, today: Date, subjectId: Long): LiveData<LessonFull?>
// GET ONE - NOW
fun getByIdNow(profileId: Int, id: Long) =
getOneNow("$QUERY WHERE timetable.profileId = $profileId AND timetable.id = $id")
@Query("""
$QUERY
WHERE timetable.profileId = :profileId AND ((type != 3 AND date > :today) OR ((type = 3 OR type = 1) AND oldDate > :today)) AND timetable.subjectId = :subjectId AND timetable.teamId = :teamId
ORDER BY id, type
LIMIT 1
""")
fun getNextWithSubjectAndTeam(profileId: Int, today: Date, subjectId: Long, teamId: Long): LiveData<LessonFull?>
@Query("UPDATE timetable SET keep = 0 WHERE profileId = :profileId AND type != -1 AND ((type != 3 AND date >= :dateFrom) OR ((type = 3 OR type = 1) AND oldDate >= :dateFrom))")
abstract fun dontKeepFromDate(profileId: Int, dateFrom: Date)
@Query("""
$QUERY
WHERE (type != 3 AND date >= :dateFrom AND date <= :dateTo) OR ((type = 3 OR type = 1) AND oldDate >= :dateFrom AND oldDate <= :dateTo)
ORDER BY profileId, id, type
""")
fun getBetweenDatesNow(dateFrom: Date, dateTo: Date): List<LessonFull>
@Query("UPDATE timetable SET keep = 0 WHERE profileId = :profileId AND type != -1 AND ((type != 3 AND date <= :dateTo) OR ((type = 3 OR type = 1) AND oldDate <= :dateTo))")
abstract fun dontKeepToDate(profileId: Int, dateTo: Date)
@Query("""
$QUERY
WHERE (type != 3 AND date >= :dateFrom AND date <= :dateTo) OR ((type = 3 OR type = 1) AND oldDate >= :dateFrom AND oldDate <= :dateTo)
ORDER BY profileId, id, type
""")
fun getBetweenDates(dateFrom: Date, dateTo: Date): LiveData<List<LessonFull>>
@Query("""
$QUERY
WHERE timetable.profileId = :profileId AND timetable.id = :lessonId
ORDER BY id, type
""")
fun getByIdNow(profileId: Int, lessonId: Long): LessonFull?
@Query("""
$QUERY
WHERE timetable.profileId = :profileId AND timetable.type NOT IN (${Lesson.TYPE_NORMAL}, ${Lesson.TYPE_NO_LESSONS}, ${Lesson.TYPE_SHIFTED_SOURCE}) AND metadata.notified = 0
""")
fun getNotNotifiedNow(profileId: Int): List<LessonFull>
@Query("""
SELECT
timetable.*,
subjects.subjectLongName AS subjectName,
teachers.teacherName ||" "|| teachers.teacherSurname AS teacherName,
oldS.subjectLongName AS oldSubjectName,
oldT.teacherName ||" "|| oldT.teacherSurname AS oldTeacherName,
metadata.seen, metadata.notified, metadata.addedDate
FROM timetable
LEFT JOIN subjects USING(profileId, subjectId)
LEFT JOIN teachers USING(profileId, teacherId)
LEFT JOIN subjects AS oldS ON timetable.profileId = oldS.profileId AND timetable.oldSubjectId = oldS.subjectId
LEFT JOIN teachers AS oldT ON timetable.profileId = oldT.profileId AND timetable.oldTeacherId = oldT.teacherId
LEFT JOIN metadata ON id = thingId AND thingType = ${Metadata.TYPE_LESSON_CHANGE} AND metadata.profileId = timetable.profileId
WHERE timetable.type NOT IN (${Lesson.TYPE_NORMAL}, ${Lesson.TYPE_NO_LESSONS}, ${Lesson.TYPE_SHIFTED_SOURCE}) AND metadata.notified = 0
""")
fun getNotNotifiedNow(): List<LessonFull>
@Query("UPDATE timetable SET keep = 0 WHERE profileId = :profileId AND type != -1 AND ((type != 3 AND date >= :dateFrom AND date <= :dateTo) OR ((type = 3 OR type = 1) AND oldDate >= :dateFrom AND oldDate <= :dateTo))")
abstract fun dontKeepBetweenDates(profileId: Int, dateFrom: Date, dateTo: Date)
}

View File

@ -1,58 +0,0 @@
/*
* Copyright (c) Kacper Ziubryniewicz 2020-1-6
*/
package pl.szczodrzynski.edziennik.data.db.entity;
import androidx.annotation.Nullable;
import androidx.room.ColumnInfo;
import androidx.room.Entity;
import androidx.room.Ignore;
import androidx.room.Index;
import pl.szczodrzynski.edziennik.utils.models.Date;
@Entity(tableName = "announcements",
primaryKeys = {"profileId", "announcementId"},
indices = {@Index(value = {"profileId"})})
public class Announcement {
public int profileId;
@ColumnInfo(name = "announcementId")
public long id;
@ColumnInfo(name = "announcementSubject")
public String subject;
@Nullable
@ColumnInfo(name = "announcementText")
public String text;
@Nullable
@ColumnInfo(name = "announcementStartDate")
public Date startDate;
@Nullable
@ColumnInfo(name = "announcementEndDate")
public Date endDate;
public long teacherId;
@Nullable
@ColumnInfo(name = "announcementIdString")
public String idString;
@Ignore
public Announcement() {}
public Announcement(int profileId, long id, String subject, String text, @Nullable Date startDate, @Nullable Date endDate, long teacherId, @Nullable String idString) {
this.profileId = profileId;
this.id = id;
this.subject = subject;
this.text = text;
this.startDate = startDate;
this.endDate = endDate;
this.teacherId = teacherId;
this.idString = idString;
}
}

View File

@ -0,0 +1,40 @@
/*
* Copyright (c) Kuba Szczodrzyński 2020-4-24.
*/
package pl.szczodrzynski.edziennik.data.db.entity
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.Ignore
import androidx.room.Index
import pl.szczodrzynski.edziennik.utils.models.Date
@Entity(tableName = "announcements",
primaryKeys = ["profileId", "announcementId"],
indices = [
Index(value = ["profileId"])
])
open class Announcement(
val profileId: Int,
@ColumnInfo(name = "announcementId")
var id: Long,
@ColumnInfo(name = "announcementSubject")
var subject: String,
@ColumnInfo(name = "announcementText")
var text: String?,
@ColumnInfo(name = "announcementStartDate")
var startDate: Date?,
@ColumnInfo(name = "announcementEndDate")
var endDate: Date?,
var teacherId: Long,
var addedDate: Long = System.currentTimeMillis()
) : Keepable() {
@ColumnInfo(name = "announcementIdString")
var idString: String? = null
@Ignore
var showAsUnseen: Boolean? = null
}

View File

@ -1,65 +0,0 @@
/*
* Copyright (c) Kacper Ziubryniewicz 2020-1-6
*/
package pl.szczodrzynski.edziennik.data.db.entity;
import androidx.annotation.NonNull;
import androidx.room.ColumnInfo;
import androidx.room.Entity;
import androidx.room.Ignore;
import androidx.room.Index;
import pl.szczodrzynski.edziennik.utils.models.Date;
import pl.szczodrzynski.edziennik.utils.models.Time;
@Entity(tableName = "attendances",
primaryKeys = {"profileId", "attendanceId", "attendanceLessonDate", "attendanceStartTime"},
indices = {@Index(value = {"profileId"})})
public class Attendance {
public int profileId;
@ColumnInfo(name = "attendanceId")
public long id;
@NonNull
@ColumnInfo(name = "attendanceLessonDate")
public Date lessonDate;
@NonNull
@ColumnInfo(name = "attendanceStartTime")
public Time startTime;
@ColumnInfo(name = "attendanceLessonTopic")
public String lessonTopic;
@ColumnInfo(name = "attendanceSemester")
public int semester;
public static final int TYPE_PRESENT = 0;
public static final int TYPE_ABSENT = 1;
public static final int TYPE_ABSENT_EXCUSED = 2;
public static final int TYPE_RELEASED = 3;
public static final int TYPE_BELATED = 4;
public static final int TYPE_BELATED_EXCUSED = 5;
public static final int TYPE_CUSTOM = 6;
public static final int TYPE_DAY_FREE = 7;
@ColumnInfo(name = "attendanceType")
public int type = TYPE_PRESENT;
public long teacherId;
public long subjectId;
@Ignore
public Attendance() {
this(-1, -1, -1, -1, 0, "", Date.getToday(), Time.getNow(), TYPE_PRESENT);
}
public Attendance(int profileId, long id, long teacherId, long subjectId, int semester, String lessonTopic, Date lessonDate, Time startTime, int type) {
this.profileId = profileId;
this.id = id;
this.teacherId = teacherId;
this.subjectId = subjectId;
this.semester = semester;
this.lessonTopic = lessonTopic;
this.lessonDate = lessonDate;
this.startTime = startTime;
this.type = type;
}
}

View File

@ -0,0 +1,68 @@
/*
* Copyright (c) Kuba Szczodrzyński 2020-4-24.
*/
package pl.szczodrzynski.edziennik.data.db.entity
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.Ignore
import androidx.room.Index
import pl.szczodrzynski.edziennik.utils.models.Date
import pl.szczodrzynski.edziennik.utils.models.Time
@Entity(tableName = "attendances",
primaryKeys = ["profileId", "attendanceId"],
indices = [
Index(value = ["profileId"])
])
open class Attendance(
val profileId: Int,
@ColumnInfo(name = "attendanceId")
var id: Long,
/** Base type ID used to count attendance stats */
@ColumnInfo(name = "attendanceBaseType")
var baseType: Int,
/** A full type name coming from the e-register */
@ColumnInfo(name = "attendanceTypeName")
var typeName: String,
/** A short name to display by default, might be different for non-standard types */
@ColumnInfo(name = "attendanceTypeShort")
val typeShort: String,
/** A short name that the e-register would display */
@ColumnInfo(name = "attendanceTypeSymbol")
var typeSymbol: String,
/** A color that the e-register would display, null falls back to app's default */
@ColumnInfo(name = "attendanceTypeColor")
var typeColor: Int?,
@ColumnInfo(name = "attendanceDate")
var date: Date,
@ColumnInfo(name = "attendanceTime")
var startTime: Time?,
@ColumnInfo(name = "attendanceSemester")
var semester: Int,
var teacherId: Long,
var subjectId: Long,
var addedDate: Long = System.currentTimeMillis()
) : Keepable() {
companion object {
const val TYPE_UNKNOWN = -1
const val TYPE_PRESENT = 0
const val TYPE_PRESENT_CUSTOM = 10 // count as presence AND show in the list
const val TYPE_ABSENT = 1
const val TYPE_ABSENT_EXCUSED = 2
const val TYPE_RELEASED = 3
const val TYPE_BELATED = 4
const val TYPE_BELATED_EXCUSED = 5
const val TYPE_DAY_FREE = 6
}
@ColumnInfo(name = "attendanceLessonTopic")
var lessonTopic: String? = null
@ColumnInfo(name = "attendanceLessonNumber")
var lessonNumber: Int? = null
@Ignore
var showAsUnseen = false
}

View File

@ -9,15 +9,16 @@ import androidx.room.Entity
@Entity(tableName = "attendanceTypes",
primaryKeys = ["profileId", "id"])
data class AttendanceType (
val profileId: Int,
val id: Long,
val name: String,
val type: Int,
val color: Int
/** Base type ID used to count attendance stats */
val baseType: Int,
/** A full type name coming from the e-register */
val typeName: String,
/** A short name to display by default, might be different for non-standard types */
val typeShort: String,
/** A short name that the e-register would display */
val typeSymbol: String,
/** A color that the e-register would display, null falls back to app's default */
val typeColor: Int?
)

View File

@ -41,7 +41,8 @@ open class Event(
var teacherId: Long,
var subjectId: Long,
var teamId: Long
var teamId: Long,
var addedDate: Long = System.currentTimeMillis()
) : Keepable() {
companion object {
const val TYPE_UNDEFINED = -2L

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) Kacper Ziubryniewicz 2020-1-6
* Copyright (c) Kuba Szczodrzyński 2020-4-24.
*/
package pl.szczodrzynski.edziennik.data.db.entity
@ -8,23 +8,11 @@ import androidx.room.Entity
import androidx.room.Ignore
import androidx.room.Index
/*public Grade(int profileId, long id, String category, int color, String description, String name, float value, float weight, int semester, long teacherId, long subjectId) {
this.profileId = profileId;
this.id = id;
this.category = category;
this.color = color;
this.description = description;
this.name = name;
this.value = value;
this.weight = weight;
this.semester = semester;
this.teacherId = teacherId;
this.subjectId = subjectId;
}*/
@Entity(tableName = "grades",
primaryKeys = ["profileId", "gradeId"],
indices = [Index(value = ["profileId"])])
indices = [
Index(value = ["profileId"])
])
open class Grade(
val profileId: Int,
@ColumnInfo(name = "gradeId")
@ -40,6 +28,7 @@ open class Grade(
var weight: Float,
@ColumnInfo(name = "gradeColor")
var color: Int,
@ColumnInfo(name = "gradeCategory")
var category: String?,
@ColumnInfo(name = "gradeDescription")
@ -50,8 +39,9 @@ open class Grade(
@ColumnInfo(name = "gradeSemester")
val semester: Int,
val teacherId: Long,
val subjectId: Long
) {
val subjectId: Long,
var addedDate: Long = System.currentTimeMillis()
) : Keepable() {
companion object {
const val TYPE_NORMAL = 0
const val TYPE_SEMESTER1_PROPOSED = 1

View File

@ -1,7 +1,6 @@
/*
* Copyright (c) Kacper Ziubryniewicz 2020-1-6
* Copyright (c) Kuba Szczodrzyński 2020-4-25.
*/
package pl.szczodrzynski.edziennik.data.db.entity
import androidx.room.Entity
@ -11,12 +10,15 @@ import pl.szczodrzynski.edziennik.utils.models.Date
import pl.szczodrzynski.edziennik.utils.models.Time
@Entity(tableName = "timetable",
primaryKeys = ["profileId", "id"],
indices = [
Index(value = ["profileId", "type", "date"]),
Index(value = ["profileId", "type", "oldDate"])
],
primaryKeys = ["profileId", "id"])
open class Lesson(val profileId: Int, var id: Long) {
])
open class Lesson(
val profileId: Int,
var id: Long
) : Keepable() {
companion object {
const val TYPE_NO_LESSONS = -1
const val TYPE_NORMAL = 0

View File

@ -1,35 +0,0 @@
/*
* Copyright (c) Kacper Ziubryniewicz 2020-1-6
*/
package pl.szczodrzynski.edziennik.data.db.entity;
import androidx.annotation.NonNull;
import androidx.room.ColumnInfo;
import androidx.room.Entity;
import androidx.room.Ignore;
import pl.szczodrzynski.edziennik.utils.models.Date;
@Entity(tableName = "luckyNumbers",
primaryKeys = {"profileId", "luckyNumberDate"})
public class LuckyNumber {
public int profileId;
@NonNull
@ColumnInfo(name = "luckyNumberDate", typeAffinity = 3)
public Date date;
@ColumnInfo(name = "luckyNumber")
public int number;
public LuckyNumber(int profileId, @NonNull Date date, int number) {
this.profileId = profileId;
this.date = date;
this.number = number;
}
@Ignore
public LuckyNumber() {
this.date = Date.getToday();
}
}

Some files were not shown because too many files have changed in this diff Show More