questionGroupService = $questionGroupService; } public function createQuestion($data, $exerciseId) { $now = now(); $groupData = []; $dataQuestion = []; $dataQuestionChoices = []; $dataQuestionBlank = []; $questionMap = []; DB::beginTransaction(); try { // 1. Chuẩn bị groupData foreach ($data as $groupKey => $value) { $groupData[] = [ 'content' => $value->title, 'exercise_id' => $exerciseId, 'is_question_order_fixed' => $value->is_question_order_fixed, 'is_option_order_fixed' => $value->is_option_order_fixed, 'position' => $groupKey + 1, 'paragraph' => $value->paragraph, 'created_at' => $now, 'updated_at' => $now, ]; } // 2. Insert group & lấy lại id QuestionGroup::insert($groupData); $groupIds = QuestionGroup::where('exercise_id', $exerciseId) ->orderByDesc('id') ->take(count($groupData)) ->get() ->reverse() ->pluck('id') ->values() ->toArray(); // 3. Chuẩn bị question $questionIndex = 0; foreach ($data as $groupKey => $value) { $groupId = $groupIds[$groupKey]; foreach ($value->questions as $qIndex => $question) { $questionType = QuestionType::where('code', $question->type)->first(); $questionTypeId = $questionType ? $questionType->id : 1; $dataQuestion[] = [ 'exercise_id' => $exerciseId, 'content' => $question->content, 'description' => $question->description ?? null, 'group_id' => $groupId, 'question_type_id' => $questionTypeId, 'level' => 2, 'score' => $question->score ?? null, 'explanation' => $question->explanation ?? null, 'hint' => $question->hint ?? null, 'created_at' => $now, 'updated_at' => $now ]; $questionMap["{$groupKey}_{$qIndex}"] = [ 'type' => $question->type, 'options' => $question->options ?? [], 'answers' => $question->answers ?? [], ]; $questionIndex++; } } // 4. Insert question & lấy lại theo custom_key Question::insert($dataQuestion); $questions = Question::where('exercise_id', $exerciseId)->get(); // $questionsByKey = $questions->keyBy(function ($item) { // return "{$item->group_id}_{$item->position}"; // hoặc dùng custom_key nếu có // }); // 5. Mapping lại options/answers $qIndex = 0; foreach ($questionMap as $key => $meta) { $questionId = $questions[$qIndex]->id ?? null; if (!$questionId) continue; if ($meta['type'] == 'multiple_choice') { foreach ($meta['options'] as $optKey => $option) { $dataQuestionChoices[] = [ 'question_id' => $questionId, 'label' => $option->label, 'content' => $option->content, 'is_correct' => $option->is_correct, 'position' => $optKey + 1, 'created_at' => $now, 'updated_at' => $now, ]; } } else { foreach ($meta['answers'] as $ansKey => $answer) { $dataQuestionBlank[] = [ 'question_id' => $questionId, 'correct_answer' => $answer->answer_true, 'other_answers' => json_encode($answer->other_answers), 'position' => $ansKey + 1, 'created_at' => $now, 'updated_at' => $now, ]; } } $qIndex++; } if (!empty($dataQuestionChoices)) { QuestionChoice::insert($dataQuestionChoices); } if (!empty($dataQuestionBlank)) { QuestionBlank::insert($dataQuestionBlank); } DB::commit(); } catch (\Throwable $e) { DB::rollBack(); throw $e; } } }