Skip to content

Commit

Permalink
feat: added ability to handle course errors
Browse files Browse the repository at this point in the history
  • Loading branch information
dixidroid committed Jul 18, 2024
1 parent d5c3b72 commit 18af4b5
Show file tree
Hide file tree
Showing 28 changed files with 906 additions and 180 deletions.
6 changes: 6 additions & 0 deletions core/src/main/java/org/openedx/core/data/api/CourseApi.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import org.openedx.core.data.model.BlocksCompletionBody
import org.openedx.core.data.model.CourseComponentStatus
import org.openedx.core.data.model.CourseDates
import org.openedx.core.data.model.CourseDatesBannerInfo
import org.openedx.core.data.model.CourseEnrollmentDetails
import org.openedx.core.data.model.CourseEnrollments
import org.openedx.core.data.model.CourseStructureModel
import org.openedx.core.data.model.HandoutsModel
Expand Down Expand Up @@ -76,4 +77,9 @@ interface CourseApi {
@Query("status") status: String? = null,
@Query("requested_fields") fields: List<String> = emptyList()
): CourseEnrollments

@GET("/api/mobile/v1/course_info/{course_id}/enrollment_details")
suspend fun getEnrollmentDetails(
@Path("course_id") courseId: String,
): CourseEnrollmentDetails
}
Original file line number Diff line number Diff line change
@@ -1,22 +1,33 @@
package org.openedx.core.data.model

import com.google.gson.annotations.SerializedName
import org.openedx.core.domain.model.CourseAccessDetails
import org.openedx.core.data.model.room.discovery.CourseAccessDetailsDb
import org.openedx.core.utils.TimeUtils
import org.openedx.core.domain.model.CourseAccessDetails as DomainCourseAccessDetails

data class CourseAccessDetails(
@SerializedName("has_unmet_prerequisites")
val hasUnmetPrerequisites: Boolean,
@SerializedName("is_too_early")
val isTooEarly: Boolean,
@SerializedName("is_staff")
val isStaff: Boolean,
@SerializedName("audit_access_expires")
val auditAccessExpires: String?,
@SerializedName("courseware_access")
var coursewareAccess: CoursewareAccess?,
) {
fun mapToDomain(): DomainCourseAccessDetails =
DomainCourseAccessDetails(
TimeUtils.iso8601ToDate(auditAccessExpires ?: ""),
coursewareAccess?.mapToDomain()
)
fun mapToDomain() = CourseAccessDetails(
hasUnmetPrerequisites = hasUnmetPrerequisites,
isTooEarly = isTooEarly,
isStaff = isStaff,
auditAccessExpires = TimeUtils.iso8601ToDate(auditAccessExpires ?: ""),
coursewareAccess = coursewareAccess?.mapToDomain(),
)

fun mapToRoomEntity(): CourseAccessDetailsDb =
CourseAccessDetailsDb(auditAccessExpires, coursewareAccess?.mapToRoomEntity())
CourseAccessDetailsDb(
hasUnmetPrerequisites, isTooEarly, isStaff,
auditAccessExpires, coursewareAccess?.mapToRoomEntity()
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package org.openedx.core.data.model

import com.google.gson.annotations.SerializedName
import org.openedx.core.domain.model.CourseEnrollmentDetails

data class CourseEnrollmentDetails(
@SerializedName("id")
val id: String,
@SerializedName("course_updates")
val courseUpdates: String,
@SerializedName("course_handouts")
val courseHandouts: String,
@SerializedName("discussion_url")
val discussionUrl: String,
@SerializedName("course_access_details")
val courseAccessDetails: CourseAccessDetails,
@SerializedName("certificate")
val certificate: Certificate?,
@SerializedName("enrollment_details")
val enrollmentDetails: EnrollmentDetails,
@SerializedName("course_info_overview")
val courseInfoOverview: CourseInfoOverview,
) {
fun mapToDomain(): CourseEnrollmentDetails {
return CourseEnrollmentDetails(
id = id,
courseUpdates = courseUpdates,
courseHandouts = courseHandouts,
discussionUrl = discussionUrl,
courseAccessDetails = courseAccessDetails.mapToDomain(),
certificate = certificate?.mapToDomain(),
enrollmentDetails = enrollmentDetails.mapToDomain(),
courseInfoOverview = courseInfoOverview.mapToDomain(),
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package org.openedx.core.data.model

import com.google.gson.annotations.SerializedName
import org.openedx.core.domain.model.CourseInfoOverview
import org.openedx.core.utils.TimeUtils

data class CourseInfoOverview(
@SerializedName("name")
val name: String,
@SerializedName("number")
val number: String,
@SerializedName("org")
val org: String,
@SerializedName("start")
val start: String?,
@SerializedName("start_display")
val startDisplay: String,
@SerializedName("start_type")
val startType: String,
@SerializedName("end")
val end: String?,
@SerializedName("is_self_paced")
val isSelfPaced: Boolean,
@SerializedName("media")
var media: Media?,
@SerializedName("course_sharing_utm_parameters")
val courseSharingUtmParameters: CourseSharingUtmParameters,
@SerializedName("course_about")
val courseAbout: String,
@SerializedName("course_modes")
val courseModes: List<CourseMode>,
) {
fun mapToDomain() = CourseInfoOverview(
name = name,
number = number,
org = org,
start = TimeUtils.iso8601ToDate(start ?: ""),
startDisplay = startDisplay,
startType = startType,
end = TimeUtils.iso8601ToDate(end ?: ""),
isSelfPaced = isSelfPaced,
media = media?.mapToDomain(),
courseSharingUtmParameters = courseSharingUtmParameters.mapToDomain(),
courseAbout = courseAbout,
courseModes = courseModes.map { it.mapToDomain() },
)
}
19 changes: 13 additions & 6 deletions core/src/main/java/org/openedx/core/data/model/CourseMode.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.openedx.core.data.model

import com.google.gson.annotations.SerializedName
import org.openedx.core.domain.model.CourseMode
import kotlin.math.ceil

/**
Expand All @@ -10,20 +11,26 @@ import kotlin.math.ceil
data class CourseMode(
@SerializedName("slug")
val slug: String?,

@SerializedName("sku")
val sku: String?,

@SerializedName("android_sku")
val androidSku: String?,

@SerializedName("ios_sku")
val iosSku: String?,
@SerializedName("min_price")
val price: Double?,

val minPrice: Double?,
var storeSku: String?,
) {
fun mapToDomain() = CourseMode(
slug = slug,
sku = sku,
androidSku = androidSku,
iosSku = iosSku,
minPrice = minPrice,
storeSku = storeSku
)
fun setStoreProductSku(storeProductPrefix: String) {
val ceilPrice = price
val ceilPrice = minPrice
?.let { ceil(it).toInt() }
?.takeIf { it > 0 }

Expand Down
25 changes: 11 additions & 14 deletions core/src/main/java/org/openedx/core/data/model/EnrollmentDetails.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,21 @@ import org.openedx.core.domain.model.EnrollmentDetails as DomainEnrollmentDetail
data class EnrollmentDetails(
@SerializedName("created")
var created: String?,

@SerializedName("date")
val date: String?,
@SerializedName("mode")
var mode: String?,

val mode: String,
@SerializedName("is_active")
var isActive: Boolean = false,

val isActive: Boolean = false,
@SerializedName("upgrade_deadline")
var upgradeDeadline: String?,
val upgradeDeadline: String?,
) {
fun mapToDomain(): DomainEnrollmentDetails {
return DomainEnrollmentDetails(
created = TimeUtils.iso8601ToDate(created ?: ""),
mode = mode,
isActive = isActive,
upgradeDeadline = TimeUtils.iso8601ToDate(upgradeDeadline ?: ""),
)
}
fun mapToDomain() = DomainEnrollmentDetails(
created = TimeUtils.iso8601ToDate(date ?: ""),
mode = mode,
isActive = isActive,
upgradeDeadline = TimeUtils.iso8601ToDate(upgradeDeadline ?: ""),
)

fun mapToRoomEntity() = EnrollmentDetailsDB(
created = created,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -267,15 +267,24 @@ data class EnrollmentDetailsDB(
}

data class CourseAccessDetailsDb(
@ColumnInfo("hasUnmetPrerequisites")
val hasUnmetPrerequisites: Boolean,
@ColumnInfo("isTooEarly")
val isTooEarly: Boolean,
@ColumnInfo("isStaff")
val isStaff: Boolean,
@ColumnInfo("auditAccessExpires")
var auditAccessExpires: String?,
@Embedded
val coursewareAccess: CoursewareAccessDb?,
) {
fun mapToDomain(): CourseAccessDetails {
return CourseAccessDetails(
TimeUtils.iso8601ToDate(auditAccessExpires ?: ""),
coursewareAccess?.mapToDomain()
hasUnmetPrerequisites = hasUnmetPrerequisites,
isTooEarly = isTooEarly,
isStaff = isStaff,
auditAccessExpires = TimeUtils.iso8601ToDate(auditAccessExpires ?: ""),
coursewareAccess = coursewareAccess?.mapToDomain()
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import java.util.Date

@Parcelize
data class CourseAccessDetails(
val hasUnmetPrerequisites: Boolean,
val isTooEarly: Boolean,
val isStaff: Boolean,
val auditAccessExpires: Date?,
val coursewareAccess: CoursewareAccess?,
) : Parcelable
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package org.openedx.core.domain.model

import android.os.Parcelable
import kotlinx.parcelize.Parcelize
import java.util.Date

@Parcelize
data class CourseEnrollmentDetails(
val id: String,
val courseUpdates: String,
val courseHandouts: String,
val discussionUrl: String,
val courseAccessDetails: CourseAccessDetails,
val certificate: Certificate?,
val enrollmentDetails: EnrollmentDetails,
val courseInfoOverview: CourseInfoOverview,
) : Parcelable {
fun isUpgradable(): Boolean {
val start = courseInfoOverview.start ?: return false
val upgradeDeadline = enrollmentDetails.upgradeDeadline ?: return false
if (enrollmentDetails.mode != "audit") return false

return start < Date() && getCourseMode() != null && upgradeDeadline > Date()
}

fun getCourseMode(): CourseMode? {
return courseInfoOverview.courseModes
.firstOrNull { it.slug == "verified" && !it.androidSku.isNullOrEmpty() }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package org.openedx.core.domain.model

import android.os.Parcelable
import kotlinx.parcelize.Parcelize
import java.util.Date

@Parcelize
data class CourseInfoOverview(
val name: String,
val number: String,
val org: String,
val start: Date?,
val startDisplay: String,
val startType: String,
val end: Date?,
val isSelfPaced: Boolean,
var media: Media?,
val courseSharingUtmParameters: CourseSharingUtmParameters,
val courseAbout: String,
val courseModes: List<CourseMode>,
) : Parcelable
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import kotlinx.parcelize.Parcelize
@Parcelize
data class CourseMode(
val slug: String?,
val sku: String?,
val androidSku: String?,
val iosSku: String?,
val minPrice: Double?,
var storeSku: String?,
) : Parcelable
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ data class EnrollmentDetails(
var created: Date?,
var mode: String?,
var isActive: Boolean,
var upgradeDeadline: Date?,
var upgradeDeadline: Date?
) : Parcelable {
val isUpgradeDeadlinePassed: Boolean
get() = TimeUtils.isDatePassed(Date(), upgradeDeadline)
Expand Down
5 changes: 5 additions & 0 deletions core/src/main/java/org/openedx/core/utils/TimeUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,11 @@ object TimeUtils {
}
}

fun getCourseAccessFormattedDate(context: Context, date: Date): String {
val resourceManager = ResourceManager(context)
return dateToCourseDate(resourceManager, date)
}

/**
* Returns the number of days difference between the given date and the current date.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import org.openedx.core.data.api.CourseApi
import org.openedx.core.data.model.BlocksCompletionBody
import org.openedx.core.data.storage.CorePreferences
import org.openedx.core.domain.model.CourseComponentStatus
import org.openedx.core.domain.model.CourseEnrollmentDetails
import org.openedx.core.domain.model.CourseStructure
import org.openedx.core.exception.NoCachedDataException
import org.openedx.core.module.db.DownloadDao
Expand Down Expand Up @@ -58,6 +59,10 @@ class CourseRepository(
return courseStructure[courseId]!!
}

suspend fun getEnrollmentDetails(courseId: String): CourseEnrollmentDetails {
return api.getEnrollmentDetails(courseId = courseId).mapToDomain()
}

suspend fun getCourseStatus(courseId: String): CourseComponentStatus {
val username = preferencesManager.user?.username ?: ""
return api.getCourseStatus(username, courseId).mapToDomain()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package org.openedx.course.domain.interactor

import org.openedx.core.BlockType
import org.openedx.core.domain.model.Block
import org.openedx.core.domain.model.CourseEnrollmentDetails
import org.openedx.core.domain.model.CourseStructure
import org.openedx.course.data.repository.CourseRepository

Expand All @@ -16,6 +17,10 @@ class CourseInteractor(
return repository.getCourseStructure(courseId, isNeedRefresh)
}

suspend fun getEnrollmentDetails(courseId: String): CourseEnrollmentDetails {
return repository.getEnrollmentDetails(courseId = courseId)
}

suspend fun getCourseStructureForVideos(
courseId: String,
isNeedRefresh: Boolean = false
Expand Down Expand Up @@ -71,5 +76,4 @@ class CourseInteractor(
suspend fun removeDownloadModel(id: String) = repository.removeDownloadModel(id)

fun getDownloadModels() = repository.getDownloadModels()

}
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,6 @@ interface CourseRouter {
fun navigateToDownloadQueue(fm: FragmentManager, descendants: List<String> = arrayListOf())

fun navigateToVideoQuality(fm: FragmentManager, videoQualityType: VideoQualityType)

fun navigateToMain(fm: FragmentManager, courseId: String?, infoType: String?, openTab: String)
}
Loading

0 comments on commit 18af4b5

Please sign in to comment.