Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added validations #19

Merged
merged 7 commits into from
Jan 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package org.sunbird.actors

import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.node.{ArrayNode, ObjectNode}
import org.apache.commons.lang3.StringUtils
import org.sunbird.`object`.importer.{ImportConfig, ImportManager}
import org.sunbird.actor.core.BaseActor
Expand All @@ -18,7 +17,6 @@ import javax.inject.Inject
import scala.collection.JavaConverters
import scala.collection.JavaConverters._
import scala.concurrent.{ExecutionContext, Future}
import com.fasterxml.jackson.databind.JsonNode

class QuestionActor @Inject()(implicit oec: OntologyEngineContext) extends BaseActor {

Expand Down Expand Up @@ -145,7 +143,7 @@ class QuestionActor @Inject()(implicit oec: OntologyEngineContext) extends BaseA
updateRequest.getContext.put("identifier", request.getContext.get("identifier"))
if(request.getRequest.containsKey("rejectComment"))
updateRequest.put("rejectComment", request.get("rejectComment").asInstanceOf[String])
updateRequest.putAll(Map("versionKey" -> node.getMetadata.get("versionKey"), "status" -> "Rejected", "prevStatus" -> node.getMetadata.get("status"), "lastStatusChangedOn" -> date, "lastUpdatedOn" -> date).asJava)
updateRequest.putAll(Map("versionKey" -> node.getMetadata.get("versionKey"), "status" -> "Rejected", "prevStatus" -> node.getMetadata.get("status"), "lastStatusChangedOn" -> date, "lastUpdatedOn" -> date, "reviewerId" -> node.getMetadata.get("reviewerId")).asJava)
AssessmentManager.updateNode(updateRequest)
})
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,22 @@
package org.sunbird.actors

import java.util

import javax.inject.Inject
import org.slf4j.{Logger, LoggerFactory}
import org.apache.commons.collections4.CollectionUtils
import org.apache.commons.lang3.StringUtils
import org.slf4j.{Logger, LoggerFactory}
import org.sunbird.`object`.importer.{ImportConfig, ImportManager}
import org.sunbird.actor.core.BaseActor
import org.sunbird.cache.impl.RedisCache
import org.sunbird.common.{DateUtils, Platform}
import org.sunbird.common.dto.{Request, Response, ResponseHandler}
import org.sunbird.common.{DateUtils, Platform}
import org.sunbird.graph.OntologyEngineContext
import org.sunbird.graph.nodes.DataNode
import org.sunbird.graph.dac.model.Node
import org.sunbird.graph.nodes.DataNode
import org.sunbird.managers.HierarchyManager.hierarchyPrefix
import org.sunbird.managers.{AssessmentManager, CopyManager, HierarchyManager, UpdateHierarchyManager}
import org.sunbird.utils.RequestUtil

import java.util
import javax.inject.Inject
import scala.collection.JavaConverters._
import scala.concurrent.{ExecutionContext, Future}

Expand Down Expand Up @@ -107,7 +106,7 @@ class QuestionSetActor @Inject()(implicit oec: OntologyEngineContext) extends Ba
val (updatedHierarchy, nodeIds) = AssessmentManager.updateHierarchy(hierarchyString.asInstanceOf[String], "Draft", node.getMetadata.getOrDefault("createdBy", "").asInstanceOf[String])
val updateReq = new Request(request)
val date = DateUtils.formatCurrentDate
updateReq.putAll(Map("identifiers" -> nodeIds, "metadata" -> Map("status" -> "Rejected", "prevStatus" -> node.getMetadata.get("status"), "lastStatusChangedOn" -> date, "lastUpdatedOn" -> date).asJava).asJava)
updateReq.putAll(Map("identifiers" -> nodeIds, "metadata" -> Map("status" -> "Rejected", "prevStatus" -> node.getMetadata.get("status"), "lastStatusChangedOn" -> date, "lastUpdatedOn" -> date, "reviewerId" -> node.getMetadata.get("reviewerId")).asJava).asJava)
val metadata: Map[String, AnyRef] = Map("status" -> "Draft", "hierarchy" -> updatedHierarchy)
val updatedMetadata = if(request.getRequest.containsKey("rejectComment")) (metadata ++ Map("rejectComment" -> request.get("rejectComment").asInstanceOf[String])) else metadata
updateHierarchyNodes(updateReq, node, updatedMetadata, nodeIds)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ object AssessmentConstants {
val MAX_SCORE = "maxScore"
val MULTIPLE = "multiple"
val QUESTION_LIST_EDITOR_URL = "question.list.search.editor.url"
val FRAMEWORK_READ_URL = "framework.read.url"
val EDITOR_STATE = "editorState"
val PARAMS = "params"
val OPTIONS = "options"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@ import org.sunbird.cache.impl.RedisCache
import org.sunbird.common.dto.Response
import org.sunbird.utils.AssessmentConstants
import play.api.libs.json.Json
import play.api.mvc.ControllerComponents
import utils.{ActorNames, ApiId, JavaJsonUtils, QuestionOperations}
import play.api.mvc.{ControllerComponents, Result}
import utils.{ActorNames, ApiId, Constants, JavaJsonUtils, QuestionOperations}

import javax.inject.{Inject, Named}
import scala.collection.JavaConverters._
import scala.concurrent.duration.Duration
import scala.concurrent.{Await, ExecutionContext, Future}


class QuestionController @Inject()(@Named(ActorNames.QUESTION_ACTOR) questionActor: ActorRef, cc: ControllerComponents, actorSystem: ActorSystem)(implicit exec: ExecutionContext) extends BaseController(cc) {

val objectType = "Question"
Expand All @@ -34,10 +35,6 @@ class QuestionController @Inject()(@Named(ActorNames.QUESTION_ACTOR) questionAct
getResult(ApiId.CREATE_QUESTION, questionActor, questionRequest)
}

def read(identifier: String, mode: Option[String], fields: Option[String]) = {
readQuestion(identifier, mode, fields, false)
}

def privateRead(identifier: String, mode: Option[String], fields: Option[String]) = Action.async { implicit request =>
val headers = commonHeaders()
val question = new java.util.HashMap().asInstanceOf[java.util.Map[String, Object]]
Expand Down Expand Up @@ -111,9 +108,6 @@ class QuestionController @Inject()(@Named(ActorNames.QUESTION_ACTOR) questionAct
getResult(ApiId.SYSTEM_UPDATE_QUESTION, questionActor, questionRequest)
}

def list(fields: Option[String]) = {
fetchQuestions(fields, false)
}

def reject(identifier: String) = Action.async { implicit request =>
val headers = commonHeaders()
Expand All @@ -139,37 +133,53 @@ class QuestionController @Inject()(@Named(ActorNames.QUESTION_ACTOR) questionAct

//Create question by uploading excel file
def uploadExcel() = Action(parse.multipartFormData) { implicit request =>
logger.info("Inside upload excel")
val questions = request.body
.file("file")
.map { filePart =>
val absolutePath = filePart.ref.path.toAbsolutePath
val fileName: String = filePart.filename
QuestionExcelParser.getQuestions(fileName, absolutePath.toFile)
val result: Option[Result] = request.body.file("file").map { filePart =>
val absolutePath = filePart.ref.path.toAbsolutePath
val fileName: String = filePart.filename
val questions: Option[IndexedSeq[Map[String, AnyRef]]] = QuestionExcelParser.getQuestions(fileName, absolutePath.toFile)

// Step 2: Validate questions based on competency and competency levels
val validatedQuestions: List[Map[String, Any]] = QuestionExcelParser.validateQuestions(questions)

// Step 3: Read framework from the API
val frameworkMap = QuestionExcelParser.frameworkRead(AssessmentConstants.FRAMEWORK_READ_URL)

// Step 4: Check if questions are valid against the framework
val isQuestionsValid: Boolean = validatedQuestions.forall { question =>
val competency: Seq[String] = question.getOrElse("subject", new java.util.ArrayList[String]()).asInstanceOf[java.util.ArrayList[String]].asScala
val difficultyLevel: Seq[String] = question.getOrElse("difficultyLevel", new java.util.ArrayList[String]()).asInstanceOf[java.util.ArrayList[String]].asScala

// Check if competency and competencyLevels are present in the framework
competency.forall(frameworkMap.contains) && difficultyLevel.forall(level => frameworkMap.getOrElse(level, Map.empty).nonEmpty)
}

if (isQuestionsValid) {
// Step 5: Process questions if valid
val futures = validatedQuestions.map { question =>
val headers = commonHeaders(request.headers)
val javaQuestion: java.util.Map[String, AnyRef] = question.mapValues(_.asInstanceOf[AnyRef]).asJava
val questionRequest = getRequest(javaQuestion, headers, QuestionOperations.createQuestionByBulkUpload.toString)
setRequestContext(questionRequest, version, objectType, schemaName)
getResponse(ApiId.CREATE_QUESTION, questionActor, questionRequest)
}

// Step 6: Await and handle the result
val f = Future.sequence(futures).map(results => results.map(_.asInstanceOf[Response]).groupBy(_.getResponseCode.toString).mapValues(listResult => {
listResult.map(result => {
setResponseEnvelope(result)
JavaJsonUtils.serialize(result.getResult)
})
})).map(f => Ok(Json.stringify(Json.toJson(f))).as("application/json"))

Await.result(f, Duration.apply("300s"))
} else {
// If questions are not valid, respond with an error
BadRequest("Invalid questions: competency or competencyLevels not present in the framework")
}
logger.info("questions after parsing " + questions)
val futures = questions.get.map(question => {
val headers = commonHeaders(request.headers)
headers.put("channel", question.get("channel"))
question.putAll(headers)
logger.info("put headers " + headers)
logger.info("creating question := {}", questions.toString)
val questionRequest = getRequest(question, headers, QuestionOperations.createQuestionByBulkUpload.toString)
logger.info("After the questionRequest")
setRequestContext(questionRequest, version, objectType, schemaName)
logger.info("After the setRequestContext")
getResponse(ApiId.CREATE_QUESTION, questionActor, questionRequest)
}
)
logger.info("After the getResponse")
val f = Future.sequence(futures).map(results => results.map(_.asInstanceOf[Response]).groupBy(_.getResponseCode.toString).mapValues(listResult => {
listResult.map(result => {
setResponseEnvelope(result)
JavaJsonUtils.serialize(result.getResult)
})
})).map(f => Ok(Json.stringify(Json.toJson(f))).as("application/json"))
logger.info("in Future sequence")
Await.result(f, Duration.apply("300s"))

// Return the result or a default BadRequest if the file is not present
result.getOrElse(BadRequest("File not provided"))
}

def createFrameworkMappingData() = Action(parse.multipartFormData) { implicit request =>
Expand Down Expand Up @@ -212,10 +222,12 @@ class QuestionController @Inject()(@Named(ActorNames.QUESTION_ACTOR) questionAct
logger.info("in Future sequence")
Await.result(f, Duration.apply("30s"))
}

def editorList(fields: Option[String]) = {
fetchQuestions(fields, true)
}
private def fetchQuestions(fields: Option[String], exclusive: Boolean) = Action.async { implicit request =>

def fetchQuestions(fields: Option[String], exclusive: Boolean) = Action.async { implicit request =>
val headers = commonHeaders()
val body = requestBody()
val question = body.getOrDefault("search", new java.util.HashMap()).asInstanceOf[java.util.Map[String, Object]];
Expand All @@ -231,7 +243,16 @@ class QuestionController @Inject()(@Named(ActorNames.QUESTION_ACTOR) questionAct
def editorRead(identifier: String, mode: Option[String], fields: Option[String]) = {
readQuestion(identifier, mode, fields, true)
}
private def readQuestion(identifier: String, mode: Option[String], fields: Option[String], exclusive: Boolean) = Action.async { implicit request =>

def list(fields: Option[String]) = {
fetchQuestions(fields, false)
}

def read(identifier: String, mode: Option[String], fields: Option[String]) = {
readQuestion(identifier, mode, fields, false)
}

def readQuestion(identifier: String, mode: Option[String], fields: Option[String], exclusive: Boolean) = Action.async { implicit request =>
val headers = commonHeaders()
val question = new java.util.HashMap().asInstanceOf[java.util.Map[String, Object]]
question.putAll(headers)
Expand Down
Loading