Add ExamPrepSubscriptionGateDisabled so learners can access exam-prep content without an IELTS or Duolingo plan. LMS subscription gating is unchanged. Co-authored-by: Cursor <cursoragent@cursor.com>
124 lines
4.6 KiB
Go
124 lines
4.6 KiB
Go
package handlers
|
|
|
|
import (
|
|
"Yimaru-Backend/internal/domain"
|
|
"fmt"
|
|
|
|
"github.com/gofiber/fiber/v2"
|
|
)
|
|
|
|
func (h *Handler) learnerHasLearnEnglishSubscription(c *fiber.Ctx) (bool, error) {
|
|
return h.learnerHasSubscriptionCategory(c, domain.SubscriptionCategoryLearnEnglish)
|
|
}
|
|
|
|
func (h *Handler) ensureLearnerPremiumContentAccess(c *fiber.Ctx, effectiveTier domain.ContentAccessTier, category domain.SubscriptionCategory) error {
|
|
role, _ := c.Locals("role").(domain.Role)
|
|
if !role.IsCustomerLearnerRole() || domain.CategorySubscriptionGateDisabled {
|
|
return nil
|
|
}
|
|
if !effectiveTier.RequiresSubscription() {
|
|
return nil
|
|
}
|
|
active, err := h.learnerHasSubscriptionCategory(c, category)
|
|
if err != nil {
|
|
return c.Status(fiber.StatusInternalServerError).JSON(domain.ErrorResponse{
|
|
Message: fmt.Sprintf("Failed to verify %s subscription", category),
|
|
Error: err.Error(),
|
|
})
|
|
}
|
|
if !active {
|
|
return c.Status(fiber.StatusForbidden).JSON(domain.ErrorResponse{
|
|
Message: fmt.Sprintf("An active %s subscription is required", humanizeSubscriptionCategory(category)),
|
|
})
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func applyProgramEffectiveAccessTier(p *domain.Program) {
|
|
p.EffectiveAccessTier = p.AccessTier
|
|
}
|
|
|
|
func applyCourseEffectiveAccessTier(course *domain.Course, program domain.Program) {
|
|
course.EffectiveAccessTier = domain.EffectiveContentAccessTier(program.AccessTier, course.AccessTier)
|
|
}
|
|
|
|
func applyModuleEffectiveAccessTier(module *domain.Module, program domain.Program, course domain.Course) {
|
|
module.EffectiveAccessTier = domain.EffectiveContentAccessTier(program.AccessTier, course.AccessTier, module.AccessTier)
|
|
}
|
|
|
|
func applyLessonEffectiveAccessTier(lesson *domain.Lesson, program domain.Program, course domain.Course, module domain.Module) {
|
|
lesson.EffectiveAccessTier = domain.EffectiveContentAccessTier(program.AccessTier, course.AccessTier, module.AccessTier, lesson.AccessTier)
|
|
}
|
|
|
|
func applyExamPrepCatalogCourseEffectiveAccessTier(cc *domain.ExamPrepCatalogCourse) {
|
|
cc.EffectiveAccessTier = cc.AccessTier
|
|
}
|
|
|
|
func applyExamPrepUnitEffectiveAccessTier(unit *domain.ExamPrepUnit, catalogCourse domain.ExamPrepCatalogCourse) {
|
|
unit.EffectiveAccessTier = domain.EffectiveContentAccessTier(catalogCourse.AccessTier, unit.AccessTier)
|
|
}
|
|
|
|
func applyExamPrepModuleEffectiveAccessTier(module *domain.ExamPrepModule, catalogCourse domain.ExamPrepCatalogCourse, unit domain.ExamPrepUnit) {
|
|
module.EffectiveAccessTier = domain.EffectiveContentAccessTier(catalogCourse.AccessTier, unit.AccessTier, module.AccessTier)
|
|
}
|
|
|
|
func applyExamPrepLessonEffectiveAccessTier(lesson *domain.ExamPrepLesson, catalogCourse domain.ExamPrepCatalogCourse, unit domain.ExamPrepUnit, module domain.ExamPrepModule) {
|
|
lesson.EffectiveAccessTier = domain.EffectiveContentAccessTier(catalogCourse.AccessTier, unit.AccessTier, module.AccessTier, lesson.AccessTier)
|
|
}
|
|
|
|
func learnerCanViewEffectiveTier(hasSubscription bool, effectiveTier domain.ContentAccessTier) bool {
|
|
return !effectiveTier.RequiresSubscription() || hasSubscription
|
|
}
|
|
|
|
func filterProgramsForLearner(items []domain.Program, hasLearnEnglish bool) []domain.Program {
|
|
filtered := make([]domain.Program, 0, len(items))
|
|
for _, item := range items {
|
|
applyProgramEffectiveAccessTier(&item)
|
|
if learnerCanViewEffectiveTier(hasLearnEnglish, item.EffectiveAccessTier) {
|
|
filtered = append(filtered, item)
|
|
}
|
|
}
|
|
return filtered
|
|
}
|
|
|
|
func filterCoursesForLearner(items []domain.Course, program domain.Program, hasLearnEnglish bool) []domain.Course {
|
|
filtered := make([]domain.Course, 0, len(items))
|
|
for i := range items {
|
|
applyCourseEffectiveAccessTier(&items[i], program)
|
|
if learnerCanViewEffectiveTier(hasLearnEnglish, items[i].EffectiveAccessTier) {
|
|
filtered = append(filtered, items[i])
|
|
}
|
|
}
|
|
return filtered
|
|
}
|
|
|
|
func filterExamPrepCatalogCoursesForLearner(items []domain.ExamPrepCatalogCourse, hasIELTS, hasDuolingo bool) []domain.ExamPrepCatalogCourse {
|
|
if domain.ExamPrepSubscriptionGateDisabled {
|
|
out := make([]domain.ExamPrepCatalogCourse, 0, len(items))
|
|
for _, item := range items {
|
|
applyExamPrepCatalogCourseEffectiveAccessTier(&item)
|
|
out = append(out, item)
|
|
}
|
|
return out
|
|
}
|
|
filtered := make([]domain.ExamPrepCatalogCourse, 0, len(items))
|
|
for _, item := range items {
|
|
applyExamPrepCatalogCourseEffectiveAccessTier(&item)
|
|
if !item.EffectiveAccessTier.RequiresSubscription() {
|
|
filtered = append(filtered, item)
|
|
continue
|
|
}
|
|
switch domain.SubscriptionCategory(item.Category) {
|
|
case domain.SubscriptionCategoryIELTS:
|
|
if hasIELTS {
|
|
filtered = append(filtered, item)
|
|
}
|
|
case domain.SubscriptionCategoryDuolingo:
|
|
if hasDuolingo {
|
|
filtered = append(filtered, item)
|
|
}
|
|
}
|
|
}
|
|
return filtered
|
|
}
|