diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9ad668b..dad870f 100755 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -26,7 +26,7 @@ jobs: run: chmod +x ./gradlew - name: Build with Gradle - run: ./gradlew detekt assembleRelease + run: ./gradlew assembleRelease - name: Upload the universal artifact uses: actions/upload-artifact@v4 @@ -34,3 +34,6 @@ jobs: path: ./composeApp/build/outputs/apk/release/composeApp-release-unsigned.apk name: progres + - name: Check linting with Detekt + run: ./gradlew detekt + diff --git a/.gitignore b/.gitignore index 7d9c0e4..a098cbf 100755 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,6 @@ captures !*.xcodeproj/project.xcworkspace/ !*.xcworkspace/contents.xcworkspacedata **/xcshareddata/WorkspaceSettings.xcsettings + +# Detekt CLI jars +detekt-*.jar diff --git a/composeApp/src/commonMain/kotlin/di/ApplicationModule.kt b/composeApp/src/commonMain/kotlin/di/ApplicationModule.kt index 34469d6..3c5e6de 100644 --- a/composeApp/src/commonMain/kotlin/di/ApplicationModule.kt +++ b/composeApp/src/commonMain/kotlin/di/ApplicationModule.kt @@ -3,14 +3,17 @@ package di import org.koin.core.module.Module import org.koin.dsl.module import utils.CredentialManager +import utils.FileStorageManager import utils.PlatformUtils val ApplicationModule: ( credentialManger: CredentialManager, - platformUtils: PlatformUtils -) -> Module = { credentialManager, platformUtils -> + platformUtils: PlatformUtils, + dataPath: String +) -> Module = { credentialManager, platformUtils, dataPath -> module { single { platformUtils } single { credentialManager } + single { FileStorageManager(dataPath) } } } diff --git a/composeApp/src/commonMain/kotlin/di/InitKoin.kt b/composeApp/src/commonMain/kotlin/di/InitKoin.kt index 1b3b69d..d45608a 100644 --- a/composeApp/src/commonMain/kotlin/di/InitKoin.kt +++ b/composeApp/src/commonMain/kotlin/di/InitKoin.kt @@ -15,7 +15,7 @@ fun initKoin( PreferencesModule(datastorePath), DomainModule, ScreenModelsModule, - ApplicationModule(credentialManager, platformUtils), + ApplicationModule(credentialManager, platformUtils, datastorePath), UpdateCheckerModule, ) } diff --git a/composeApp/src/commonMain/kotlin/utils/FileStorageManager.kt b/composeApp/src/commonMain/kotlin/utils/FileStorageManager.kt new file mode 100644 index 0000000..791a04d --- /dev/null +++ b/composeApp/src/commonMain/kotlin/utils/FileStorageManager.kt @@ -0,0 +1,153 @@ +package utils + +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import okio.FileSystem +import okio.Path.Companion.toPath + +/** + * Manages file storage operations for profile pictures and university logos + */ +class FileStorageManager( + private val baseDataPath: String +) { + private val fileSystem = FileSystem.SYSTEM + private val imagesDir = "$baseDataPath/images".toPath() + private val profilePicturesDir = imagesDir / "profiles" + private val universityLogosDir = imagesDir / "logos" + + init { + // Ensure directories exist + try { + fileSystem.createDirectories(profilePicturesDir) + fileSystem.createDirectories(universityLogosDir) + } catch (e: Exception) { + e.printStackTrace() + } + } + + /** + * Saves a profile picture and returns the file path + */ + suspend fun saveProfilePicture(studentId: String, imageData: ByteArray): String? = withContext(Dispatchers.IO) { + try { + val fileName = "profile_${studentId.replace(Regex("[^a-zA-Z0-9]"), "_")}.jpg" + val filePath = profilePicturesDir / fileName + + fileSystem.write(filePath) { + write(imageData) + } + + filePath.toString() + } catch (e: Exception) { + e.printStackTrace() + null + } + } + + /** + * Saves a university logo and returns the file path + */ + suspend fun saveUniversityLogo(establishmentId: String, imageData: ByteArray): String? = withContext( + Dispatchers.IO + ) { + try { + val fileName = "logo_${establishmentId.replace(Regex("[^a-zA-Z0-9]"), "_")}.jpg" + val filePath = universityLogosDir / fileName + + fileSystem.write(filePath) { + write(imageData) + } + + filePath.toString() + } catch (e: Exception) { + e.printStackTrace() + null + } + } + + /** + * Loads image data from a file path + */ + suspend fun loadImage(filePath: String): ByteArray? = withContext(Dispatchers.IO) { + try { + val path = filePath.toPath() + if (fileSystem.exists(path)) { + fileSystem.read(path) { + readByteArray() + } + } else { + null + } + } catch (e: Exception) { + e.printStackTrace() + null + } + } + + /** + * Deletes an image file + */ + suspend fun deleteImage(filePath: String): Boolean = withContext(Dispatchers.IO) { + try { + val path = filePath.toPath() + if (fileSystem.exists(path)) { + fileSystem.delete(path) + true + } else { + false + } + } catch (e: Exception) { + e.printStackTrace() + false + } + } + + /** + * Deletes all profile pictures + */ + suspend fun deleteAllProfilePictures(): Boolean = withContext(Dispatchers.IO) { + try { + if (fileSystem.exists(profilePicturesDir)) { + fileSystem.deleteRecursively(profilePicturesDir) + fileSystem.createDirectories(profilePicturesDir) + true + } else { + true + } + } catch (e: Exception) { + e.printStackTrace() + false + } + } + + /** + * Deletes all university logos + */ + suspend fun deleteAllUniversityLogos(): Boolean = withContext(Dispatchers.IO) { + try { + if (fileSystem.exists(universityLogosDir)) { + fileSystem.deleteRecursively(universityLogosDir) + fileSystem.createDirectories(universityLogosDir) + true + } else { + true + } + } catch (e: Exception) { + e.printStackTrace() + false + } + } + + /** + * Checks if an image file exists + */ + fun imageExists(filePath: String): Boolean { + return try { + fileSystem.exists(filePath.toPath()) + } catch (e: Exception) { + e.printStackTrace() + false + } + } +} diff --git a/config/detekt/detekt.yml b/config/detekt/detekt.yml index dffb422..4989d2c 100644 --- a/config/detekt/detekt.yml +++ b/config/detekt/detekt.yml @@ -23,6 +23,8 @@ style: UnusedPrivateMember: ignoreAnnotated: - "Preview" + PrintStackTrace: + active: false exceptions: SwallowedException: diff --git a/domain/data/src/androidMain/kotlin/mehiz/abdallah/progres/data/database/DatabaseModule.android.kt b/domain/data/src/androidMain/kotlin/mehiz/abdallah/progres/data/database/DatabaseModule.android.kt index 82a1009..a935529 100644 --- a/domain/data/src/androidMain/kotlin/mehiz/abdallah/progres/data/database/DatabaseModule.android.kt +++ b/domain/data/src/androidMain/kotlin/mehiz/abdallah/progres/data/database/DatabaseModule.android.kt @@ -19,6 +19,26 @@ actual val ProgresDatabaseModule = module { override fun onOpen(db: SupportSQLiteDatabase) { db.setForeignKeyConstraintsEnabled(true) } + + override fun onUpgrade( + db: SupportSQLiteDatabase, + oldVersion: Int, + newVersion: Int + ) { + // Handle migration from BLOB to file storage + // Clear affected tables to force fresh sync with new schema + if (oldVersion < newVersion) { + try { + db.execSQL("DROP TABLE IF EXISTS IndividualInfoTable") + db.execSQL("DROP TABLE IF EXISTS StudentCardTable") + // Recreate tables with new schema + onCreate(db) + } catch (e: Exception) { + // If migration fails, recreate database + super.onUpgrade(db, oldVersion, newVersion) + } + } + } } ), ) diff --git a/domain/data/src/commonMain/kotlin/mehiz/abdallah/progres/data/daos/IndividualInfoDao.kt b/domain/data/src/commonMain/kotlin/mehiz/abdallah/progres/data/daos/IndividualInfoDao.kt index 8bc7603..23a9c77 100644 --- a/domain/data/src/commonMain/kotlin/mehiz/abdallah/progres/data/daos/IndividualInfoDao.kt +++ b/domain/data/src/commonMain/kotlin/mehiz/abdallah/progres/data/daos/IndividualInfoDao.kt @@ -2,9 +2,11 @@ package mehiz.abdallah.progres.data.daos import mehiz.abdallah.progres.data.db.IndividualInfoTable import mehiz.abdallah.progres.data.db.ProgresDB +import utils.FileStorageManager class IndividualInfoDao( - db: ProgresDB + db: ProgresDB, + private val fileStorageManager: FileStorageManager ) { private val queries = db.individualInfoTableQueries @@ -18,7 +20,7 @@ class IndividualInfoDao( firstNameLatin = firstNameLatin, lastNameLatin = lastNameLatin, lastNameArabic = lastNameArabic, - photo = photo, + photoPath = photoPath, dateOfBirth = dateOfBirth, placeOfBirthLatin = placeOfBirthLatin, placeOfBirthArabic = placeOfBirthArabic, @@ -30,11 +32,18 @@ class IndividualInfoDao( return queries.getById(id).executeAsOneOrNull() } - fun getIndividualPhotoById(id: Long): ByteArray? { - return queries.getStudentPhotoById(id).executeAsOne().photo + fun getIndividualPhotoPathById(id: Long): String? { + return queries.getStudentPhotoPathById(id).executeAsOneOrNull() } - fun deleteAllIndividualInfo() { + suspend fun getIndividualPhotoById(id: Long): ByteArray? { + val photoPath = getIndividualPhotoPathById(id) + return photoPath?.let { fileStorageManager.loadImage(it) } + } + + suspend fun deleteAllIndividualInfo() { + // Delete all profile pictures before clearing database + fileStorageManager.deleteAllProfilePictures() queries.delete() } diff --git a/domain/data/src/commonMain/kotlin/mehiz/abdallah/progres/data/daos/StudentCardDao.kt b/domain/data/src/commonMain/kotlin/mehiz/abdallah/progres/data/daos/StudentCardDao.kt index efe0518..5a1214d 100644 --- a/domain/data/src/commonMain/kotlin/mehiz/abdallah/progres/data/daos/StudentCardDao.kt +++ b/domain/data/src/commonMain/kotlin/mehiz/abdallah/progres/data/daos/StudentCardDao.kt @@ -2,10 +2,12 @@ package mehiz.abdallah.progres.data.daos import mehiz.abdallah.progres.data.db.ProgresDB import mehiz.abdallah.progres.data.db.StudentCardTable +import utils.FileStorageManager @Suppress("TooManyFunctions") class StudentCardDao( - db: ProgresDB + db: ProgresDB, + private val fileStorageManager: FileStorageManager ) { private val queries = db.studentCardTableQueries @@ -37,7 +39,7 @@ class StudentCardDao( levelId = levelId, establishmentStringLatin = establishmentStringLatin, establishmentStringArabic = establishmentStringArabic, - establishmentLogo = establishmentLogo, + establishmentLogoPath = establishmentLogoPath, cycleStringLatin = cycleStringLatin, cycleStringArabic = cycleStringArabic ) @@ -60,11 +62,18 @@ class StudentCardDao( return queries.getCardByAcademicYear(id).executeAsOne() } - fun deleteCard(id: Long) { + suspend fun deleteCard(id: Long) { + // Get the establishment logo path before deleting + val card = queries.getCard(id).executeAsOneOrNull() + card?.establishmentLogoPath?.let { logoPath -> + fileStorageManager.deleteImage(logoPath) + } queries.deleteCardWithId(id) } - fun deleteAllCards() { + suspend fun deleteAllCards() { + // Delete all university logos before clearing database + fileStorageManager.deleteAllUniversityLogos() queries.deleteAllCards() } } diff --git a/domain/data/src/commonMain/sqldelight/mehiz/abdallah/progres/data/db/IndividualInfoTable.sq b/domain/data/src/commonMain/sqldelight/mehiz/abdallah/progres/data/db/IndividualInfoTable.sq index d7b951d..a1e01e7 100644 --- a/domain/data/src/commonMain/sqldelight/mehiz/abdallah/progres/data/db/IndividualInfoTable.sq +++ b/domain/data/src/commonMain/sqldelight/mehiz/abdallah/progres/data/db/IndividualInfoTable.sq @@ -1,4 +1,4 @@ -CREATE TABLE IndividualInfoTable( +CREATE TABLE IF NOT EXISTS IndividualInfoTable( id INTEGER NOT NULL PRIMARY KEY, firstNameArabic TEXT NOT NULL, firstNameLatin TEXT NOT NULL, @@ -7,7 +7,7 @@ lastNameLatin TEXT NOT NULL, dateOfBirth TEXT NOT NULL, placeOfBirthArabic TEXT, placeOfBirthLatin TEXT, -photo BLOB, +photoPath TEXT, uuid TEXT NOT NULL ); @@ -21,7 +21,7 @@ lastNameLatin, dateOfBirth, placeOfBirthArabic, placeOfBirthLatin, -photo, +photoPath, uuid ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?); @@ -31,8 +31,8 @@ SELECT * FROM IndividualInfoTable LIMIT 1; getById: SELECT * FROM IndividualInfoTable WHERE id = :id; -getStudentPhotoById: -SELECT photo FROM IndividualInfoTable WHERE id = :id; +getStudentPhotoPathById: +SELECT photoPath FROM IndividualInfoTable WHERE id = :id; delete: DELETE FROM IndividualInfoTable; diff --git a/domain/data/src/commonMain/sqldelight/mehiz/abdallah/progres/data/db/StudentCardTable.sq b/domain/data/src/commonMain/sqldelight/mehiz/abdallah/progres/data/db/StudentCardTable.sq index ac7a404..4005be1 100644 --- a/domain/data/src/commonMain/sqldelight/mehiz/abdallah/progres/data/db/StudentCardTable.sq +++ b/domain/data/src/commonMain/sqldelight/mehiz/abdallah/progres/data/db/StudentCardTable.sq @@ -13,7 +13,7 @@ individualPlaceOfBirthArabic TEXT, individualPlaceOfBirthLatin TEXT, establishmentStringArabic TEXT NOT NULL, establishmentStringLatin TEXT NOT NULL, -establishmentLogo BLOB, +establishmentLogoPath TEXT, levelId INTEGER NOT NULL, levelStringLongArabic TEXT NOT NULL, levelStringLongLatin TEXT NOT NULL, @@ -44,7 +44,7 @@ individualPlaceOfBirthLatin, establishmentStringArabic, establishmentStringLatin, levelId, -establishmentLogo, +establishmentLogoPath, levelStringLongArabic, levelStringLongLatin, registrationNumber, diff --git a/domain/src/commonMain/kotlin/mehiz/abdallah/progres/domain/ImageMigrationUseCase.kt b/domain/src/commonMain/kotlin/mehiz/abdallah/progres/domain/ImageMigrationUseCase.kt new file mode 100644 index 0000000..1050b10 --- /dev/null +++ b/domain/src/commonMain/kotlin/mehiz/abdallah/progres/domain/ImageMigrationUseCase.kt @@ -0,0 +1,55 @@ +package mehiz.abdallah.progres.domain + +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import mehiz.abdallah.progres.data.daos.IndividualInfoDao +import mehiz.abdallah.progres.data.daos.StudentCardDao +import utils.FileStorageManager + +/** + * Handles migration of image data from database BLOBs to file storage + * This is used during the transition period to ensure compatibility + */ +class ImageMigrationUseCase( + private val individualInfoDao: IndividualInfoDao, + private val studentCardDao: StudentCardDao, + private val fileStorageManager: FileStorageManager +) { + + /** + * Checks if migration is needed and suggests a refresh + * Since this is a significant change, we recommend users refresh their data + * to get images stored in the new file format + */ + suspend fun isMigrationNeeded(): Boolean = withContext(Dispatchers.IO) { + // Check if there are any records that might have old BLOB data + // Since we changed schema, old data will be cleaned during refresh + val individualInfo = individualInfoDao.getIndividualInfo() + val studentCards = studentCardDao.getAllStudentCards() + + // If no data exists, no migration needed + if (individualInfo == null && studentCards.isEmpty()) { + return@withContext false + } + + // Check if we have photo paths (new format) or if they're missing (needs refresh) + val needsPhotoMigration = individualInfo?.photoPath == null + val needsLogoMigration = studentCards.any { it.establishmentLogoPath == null } + + needsPhotoMigration || needsLogoMigration + } + + /** + * Clears all data to force a fresh sync with the new file storage format + * This is the safest migration approach for this type of schema change + */ + suspend fun forceFreshSync() = withContext(Dispatchers.IO) { + // Clean up any existing files + fileStorageManager.deleteAllProfilePictures() + fileStorageManager.deleteAllUniversityLogos() + + // Clear database to force fresh sync + individualInfoDao.deleteAllIndividualInfo() + studentCardDao.deleteAllCards() + } +} diff --git a/domain/src/commonMain/kotlin/mehiz/abdallah/progres/domain/StudentCardUseCase.kt b/domain/src/commonMain/kotlin/mehiz/abdallah/progres/domain/StudentCardUseCase.kt index c8b91cf..10495d9 100644 --- a/domain/src/commonMain/kotlin/mehiz/abdallah/progres/domain/StudentCardUseCase.kt +++ b/domain/src/commonMain/kotlin/mehiz/abdallah/progres/domain/StudentCardUseCase.kt @@ -7,68 +7,98 @@ import mehiz.abdallah.progres.domain.models.IndividualInfoModel import mehiz.abdallah.progres.domain.models.StudentCardModel import mehiz.abdallah.progres.domain.models.toModel import mehiz.abdallah.progres.domain.models.toTable +import utils.FileStorageManager import kotlin.uuid.ExperimentalUuidApi class StudentCardUseCase( - private val api: ProgresApi, - private val studentCardDao: StudentCardDao, - private val individualInfoDao: IndividualInfoDao, - private val userAuthUseCase: UserAuthUseCase, + private val api: ProgresApi, + private val studentCardDao: StudentCardDao, + private val individualInfoDao: IndividualInfoDao, + private val userAuthUseCase: UserAuthUseCase, + private val fileStorageManager: FileStorageManager, ) { - suspend fun getLatestStudentPhoto(refresh: Boolean): ByteArray? { - return getLatestStudentCard(refresh).photo - } - - @OptIn(ExperimentalUuidApi::class) - suspend fun getAllStudentCards(refresh: Boolean): List { - studentCardDao.getAllStudentCards().let { - val individual = getIndividualInfo(false) - if (it.isNotEmpty() && !refresh) { - return it.map { it.toModel(individual.photo) } - } - } - val token = userAuthUseCase.getToken() - val auth = userAuthUseCase.getFullUserAuth() - val individual = getIndividualInfo(refresh) - val establishmentLogo = api.getEstablishmentLogo(auth.establishmentId, token) - val cards = api.getStudentCards(auth.uuid, token).map { card -> - card.toTable(api.getTransportState(auth.uuid, card.id, token)?.transportPayed == true, establishmentLogo) + suspend fun getLatestStudentPhoto(refresh: Boolean): ByteArray? { + return getLatestStudentCard(refresh).photo } - if (refresh) studentCardDao.deleteAllCards() - return cards.map { - studentCardDao.insert(it) - it.toModel( - photo = individual.photo, - ) + + @OptIn(ExperimentalUuidApi::class) + suspend fun getAllStudentCards(refresh: Boolean): List { + studentCardDao.getAllStudentCards().let { cards -> + val individual = getIndividualInfo(false) + if (cards.isNotEmpty() && !refresh) { + return cards.map { card -> + // Load establishment logo from file + val logoBytes = card.establishmentLogoPath?.let { + fileStorageManager.loadImage(it) + } + card.toModel(individual.photo).copy(establishmentLogo = logoBytes) + } + } + } + val token = userAuthUseCase.getToken() + val auth = userAuthUseCase.getFullUserAuth() + val individual = getIndividualInfo(refresh) + + // Download and save establishment logo + val establishmentLogoBytes = api.getEstablishmentLogo(auth.establishmentId, token) + val establishmentId = auth.establishmentId.toString() + val logoPath = establishmentLogoBytes?.let { + fileStorageManager.saveUniversityLogo(establishmentId, it) + } + + val cards = api.getStudentCards(auth.uuid, token).map { card -> + card.toTable(api.getTransportState(auth.uuid, card.id, token)?.transportPayed == true, logoPath) + } + + if (refresh) studentCardDao.deleteAllCards() + return cards.map { card -> + studentCardDao.insert(card) + card.toModel(photo = individual.photo).copy(establishmentLogo = establishmentLogoBytes) + } } - } - suspend fun getLatestStudentCard(refresh: Boolean): StudentCardModel { - return if (refresh) { - getAllStudentCards(true).maxBy { it.id } - } else { - studentCardDao.getLatestStudentCard()?.let { - val individualInfo = getIndividualInfo(false) - it.toModel(individualInfo.photo) - } ?: getAllStudentCards(false).maxBy { it.id } + suspend fun getLatestStudentCard(refresh: Boolean): StudentCardModel { + return if (refresh) { + getAllStudentCards(true).maxBy { it.id } + } else { + studentCardDao.getLatestStudentCard()?.let { card -> + val individualInfo = getIndividualInfo(false) + // Load establishment logo from file + val logoBytes = card.establishmentLogoPath?.let { + fileStorageManager.loadImage(it) + } + card.toModel(individualInfo.photo).copy(establishmentLogo = logoBytes) + } ?: getAllStudentCards(false).maxBy { it.id } + } } - } - @OptIn(ExperimentalUuidApi::class) - suspend fun getIndividualInfo(refresh: Boolean): IndividualInfoModel { - individualInfoDao.getIndividualInfo()?.let { - if (!refresh) return it.toModel() + @OptIn(ExperimentalUuidApi::class) + suspend fun getIndividualInfo(refresh: Boolean): IndividualInfoModel { + individualInfoDao.getIndividualInfo()?.let { table -> + if (!refresh) { + val photo = individualInfoDao.getIndividualPhotoById(table.id) + return table.toModel().copy(photo = photo) + } + } + val uuid = userAuthUseCase.getUuid() + val token = userAuthUseCase.getToken() + val info = api.getIndividualInfo(uuid, token) + val photoBytes = api.getStudentPhoto(uuid = uuid, token = token) + + if (refresh) individualInfoDao.deleteAllIndividualInfo() + + // Save photo to file and get path + val photoPath = photoBytes?.let { + fileStorageManager.saveProfilePicture(uuid.toString(), it) + } + + return info.let { dto -> + val table = dto.toTable( + photoPath = photoPath, + uuid = uuid.toString(), + ) + individualInfoDao.insert(table) + table.toModel().copy(photo = photoBytes) + } } - val uuid = userAuthUseCase.getUuid() - val token = userAuthUseCase.getToken() - val info = api.getIndividualInfo(uuid, token) - val photo = api.getStudentPhoto(uuid = uuid, token = token) - if (refresh) individualInfoDao.deleteAllIndividualInfo() - return info.let { dto -> - dto.toTable( - photo, - uuid = uuid.toString(), - ).also { individualInfoDao.insert(it) } - }.toModel() - } } diff --git a/domain/src/commonMain/kotlin/mehiz/abdallah/progres/domain/di/DomainModule.kt b/domain/src/commonMain/kotlin/mehiz/abdallah/progres/domain/di/DomainModule.kt index edf47b9..eb8e055 100755 --- a/domain/src/commonMain/kotlin/mehiz/abdallah/progres/domain/di/DomainModule.kt +++ b/domain/src/commonMain/kotlin/mehiz/abdallah/progres/domain/di/DomainModule.kt @@ -11,6 +11,7 @@ import mehiz.abdallah.progres.domain.DischargeUseCase import mehiz.abdallah.progres.domain.ExamGradeUseCase import mehiz.abdallah.progres.domain.ExamScheduleUseCase import mehiz.abdallah.progres.domain.GroupUseCase +import mehiz.abdallah.progres.domain.ImageMigrationUseCase import mehiz.abdallah.progres.domain.StudentCardUseCase import mehiz.abdallah.progres.domain.SubjectScheduleUseCase import mehiz.abdallah.progres.domain.SubjectUseCase @@ -39,4 +40,5 @@ val DomainModule = module { singleOf(::UserAuthUseCase) singleOf(::DischargeUseCase) singleOf(::AccommodationUseCase) + singleOf(::ImageMigrationUseCase) } diff --git a/domain/src/commonMain/kotlin/mehiz/abdallah/progres/domain/models/IndividualInfoModel.kt b/domain/src/commonMain/kotlin/mehiz/abdallah/progres/domain/models/IndividualInfoModel.kt index 402f6d4..6f20ee1 100644 --- a/domain/src/commonMain/kotlin/mehiz/abdallah/progres/domain/models/IndividualInfoModel.kt +++ b/domain/src/commonMain/kotlin/mehiz/abdallah/progres/domain/models/IndividualInfoModel.kt @@ -19,7 +19,7 @@ data class IndividualInfoModel( ) fun IndividualInfoDto.toTable( - photo: ByteArray?, + photoPath: String?, uuid: String, ): IndividualInfoTable { return IndividualInfoTable( @@ -32,7 +32,7 @@ fun IndividualInfoDto.toTable( firstNameLatin = prenomLatin, lastNameLatin = nomLatin, lastNameArabic = nomArabe, - photo = photo, + photoPath = photoPath, ) } @@ -47,6 +47,6 @@ fun IndividualInfoTable.toModel(): IndividualInfoModel { firstNameLatin = firstNameLatin, lastNameArabic = lastNameArabic, lastNameLatin = lastNameLatin, - photo = photo + photo = null // Will be loaded separately by use case ) } diff --git a/domain/src/commonMain/kotlin/mehiz/abdallah/progres/domain/models/StudentCardModel.kt b/domain/src/commonMain/kotlin/mehiz/abdallah/progres/domain/models/StudentCardModel.kt index e5b9242..3ce85d8 100644 --- a/domain/src/commonMain/kotlin/mehiz/abdallah/progres/domain/models/StudentCardModel.kt +++ b/domain/src/commonMain/kotlin/mehiz/abdallah/progres/domain/models/StudentCardModel.kt @@ -38,7 +38,7 @@ data class StudentCardModel( fun StudentCardDto.toTable( isTransportPaid: Boolean, - establishmentLogo: ByteArray?, + establishmentLogoPath: String?, ): StudentCardTable { return StudentCardTable( academicYearString = anneeAcademiqueCode, @@ -66,7 +66,7 @@ fun StudentCardDto.toTable( levelId = niveauId, establishmentStringLatin = llEtablissementLatin, establishmentStringArabic = llEtablissementArabe, - establishmentLogo = establishmentLogo, + establishmentLogoPath = establishmentLogoPath, cycleStringLatin = refLibelleCycle, cycleStringArabic = refLibelleCycleAr, ) @@ -102,7 +102,7 @@ fun StudentCardTable.toModel( situationId = situationId, establishmentStringLatin = establishmentStringLatin, establishmentStringArabic = establishmentStringLatin, - establishmentLogo = establishmentLogo, + establishmentLogo = null, // Will be loaded separately by use case cycleStringLatin = cycleStringLatin, cycleStringArabic = cycleStringArabic )