diff --git a/.ruby-version b/.ruby-version new file mode 100644 index 000000000..0aec50e6e --- /dev/null +++ b/.ruby-version @@ -0,0 +1 @@ +3.1.4 diff --git a/app/api/entities/unit_entity.rb b/app/api/entities/unit_entity.rb index 4ac79cb15..890daf823 100644 --- a/app/api/entities/unit_entity.rb +++ b/app/api/entities/unit_entity.rb @@ -15,6 +15,9 @@ def can_read_unit_config?(my_role) expose :code expose :id expose :name + expose :creditpoint + expose :prerequisite + expose :corequisite expose :my_role do |unit, options| role = options[:my_role] role = unit.role_for(options[:user]) if role.nil? @@ -51,17 +54,12 @@ def can_read_unit_config?(my_role) expose :learning_outcomes, using: LearningOutcomeEntity, as: :ilos, unless: :summary_only expose :tutorial_streams, using: TutorialStreamEntity, unless: :summary_only - # Expose staff before tutorials, so that their details are available expose :staff, using: UnitRoleEntity, unless: :summary_only expose :tutorials, using: TutorialEntity, unless: :summary_only - # expose :tutorial_enrolments, using: TutorialEnrolmentEntity, unless: :summary_only, if: lambda { |unit, options| is_staff?(options[:my_role]) } expose :task_definitions, using: TaskDefinitionEntity, unless: :summary_only expose :task_outcome_alignments, using: TaskOutcomeAlignmentEntity, unless: :summary_only expose :group_sets, using: GroupSetEntity, unless: :summary_only expose :groups, using: GroupEntity, unless: :summary_only - # expose :group_memberships, using: GroupMembershipEntity, unless: :summary_only do |unit, options| - # unit.group_memberships.where(active: true) - # end end end diff --git a/app/api/units_api.rb b/app/api/units_api.rb index bbdc93fca..ab928f129 100644 --- a/app/api/units_api.rb +++ b/app/api/units_api.rb @@ -75,6 +75,9 @@ class UnitsApi < Grape::API optional :teaching_period_id, type: Integer optional :start_date, type: Date optional :end_date, type: Date + optional :creditpoint, type: Integer + optional :prerequisite, type: String + optional :corequisite, type: String optional :main_convenor_id, type: Integer optional :auto_apply_extension_before_deadline, type: Boolean, desc: 'Indicates if extensions before the deadline should be automatically applied' optional :send_notifications, type: Boolean, desc: 'Indicates if emails should be sent on updates each week' @@ -117,7 +120,11 @@ class UnitsApi < Grape::API :extension_weeks_on_resubmit_request, :allow_student_change_tutorial, :overseer_image_id, - :assessment_enabled) + :assessment_enabled, + :creditpoint, + :prerequisite, + :corequisite + ) if unit.teaching_period_id.present? && (unit_parameters.key?(:start_date) || unit_parameters['teaching_period_id'] == -1) unit.teaching_period = nil @@ -151,10 +158,13 @@ class UnitsApi < Grape::API optional :teaching_period_id, type: Integer optional :start_date, type: Date optional :end_date, type: Date + optional :creditpoint, type: Integer + optional :prerequisite, type: String + optional :corequisite, type: String optional :main_convenor_user_id, type: Integer optional :auto_apply_extension_before_deadline, type: Boolean, desc: 'Indicates if extensions before the deadline should be automatically applied', default: true optional :send_notifications, type: Boolean, desc: 'Indicates if emails should be sent on updates each week', default: true - optional :enable_sync_timetable, type: Boolean, desc: 'Sync to timetable automatically if supported by deployment', default: true + optional :enable_sync_timetable, type: Boolean, desc: 'Sync to timetable automatically if supported by deployment', default: true optional :enable_sync_enrolments, type: Boolean, desc: 'Sync student enrolments automatically if supported by deployment', default: true optional :allow_student_extension_requests, type: Boolean, desc: 'Can turn on/off student extension requests', default: true optional :extension_weeks_on_resubmit_request, type: Integer, desc: 'Determines the number of weeks extension on a resubmit request', default: 1 @@ -188,6 +198,9 @@ class UnitsApi < Grape::API :extension_weeks_on_resubmit_request, :portfolio_auto_generation_date, :allow_student_change_tutorial, + :creditpoint, + :prerequisite, + :corequisite ) # Identify main convenor - ensure they have the correct role diff --git a/db/migrate/20250429043824_add_credit_points_to_units.rb b/db/migrate/20250429043824_add_credit_points_to_units.rb new file mode 100644 index 000000000..35e91da2c --- /dev/null +++ b/db/migrate/20250429043824_add_credit_points_to_units.rb @@ -0,0 +1,5 @@ +class AddCreditPointsToUnits < ActiveRecord::Migration[7.1] + def change + add_column :units, :creditpoint, :integer + end +end diff --git a/db/migrate/20250429193655_add_prerequisite_to_units.rb b/db/migrate/20250429193655_add_prerequisite_to_units.rb new file mode 100644 index 000000000..09acf018a --- /dev/null +++ b/db/migrate/20250429193655_add_prerequisite_to_units.rb @@ -0,0 +1,5 @@ +class AddPrerequisiteToUnits < ActiveRecord::Migration[7.1] + def change + add_column :units, :prerequisite, :string + end +end diff --git a/db/migrate/20250430035259_add_corequisite_to_units.rb b/db/migrate/20250430035259_add_corequisite_to_units.rb new file mode 100644 index 000000000..473d069a4 --- /dev/null +++ b/db/migrate/20250430035259_add_corequisite_to_units.rb @@ -0,0 +1,5 @@ +class AddCorequisiteToUnits < ActiveRecord::Migration[7.1] + def change + add_column :units, :corequisite, :string + end +end diff --git a/db/migrate/20250430050449_set_default_for_corequisite_and_prerequisite_in_units.rb b/db/migrate/20250430050449_set_default_for_corequisite_and_prerequisite_in_units.rb new file mode 100644 index 000000000..f51e12675 --- /dev/null +++ b/db/migrate/20250430050449_set_default_for_corequisite_and_prerequisite_in_units.rb @@ -0,0 +1,6 @@ +class SetDefaultForCorequisiteAndPrerequisiteInUnits < ActiveRecord::Migration[7.1] + def change + change_column_default :units, :corequisite, from: nil, to: "Nil" + change_column_default :units, :prerequisite, from: nil, to: "Nil" + end +end diff --git a/db/schema.rb b/db/schema.rb index 6daa71ebf..4f0391301 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,8 +10,8 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.1].define(version: 2024_05_28_223908) do - create_table "activity_types", charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| +ActiveRecord::Schema[7.1].define(version: 2025_04_30_050449) do + create_table "activity_types", charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t| t.string "name", null: false t.string "abbreviation", null: false t.datetime "created_at", null: false @@ -20,21 +20,21 @@ t.index ["name"], name: "index_activity_types_on_name", unique: true end - create_table "auth_tokens", charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| + create_table "auth_tokens", charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t| t.datetime "auth_token_expiry", null: false t.bigint "user_id" t.string "authentication_token", null: false t.index ["user_id"], name: "index_auth_tokens_on_user_id" end - create_table "breaks", charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| + create_table "breaks", charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t| t.datetime "start_date", null: false t.integer "number_of_weeks", null: false t.bigint "teaching_period_id" t.index ["teaching_period_id"], name: "index_breaks_on_teaching_period_id" end - create_table "campuses", charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| + create_table "campuses", charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t| t.string "name", null: false t.integer "mode", null: false t.string "abbreviation", null: false @@ -44,7 +44,7 @@ t.index ["name"], name: "index_campuses_on_name", unique: true end - create_table "comments_read_receipts", charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| + create_table "comments_read_receipts", charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t| t.bigint "task_comment_id", null: false t.bigint "user_id", null: false t.datetime "created_at", null: false @@ -54,7 +54,7 @@ t.index ["user_id"], name: "index_comments_read_receipts_on_user_id" end - create_table "discussion_comments", charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| + create_table "discussion_comments", charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t| t.datetime "time_started" t.datetime "time_completed" t.integer "number_of_prompts" @@ -62,7 +62,7 @@ t.datetime "updated_at", null: false end - create_table "group_memberships", charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| + create_table "group_memberships", charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t| t.bigint "group_id" t.bigint "project_id" t.boolean "active", default: true @@ -72,7 +72,7 @@ t.index ["project_id"], name: "index_group_memberships_on_project_id" end - create_table "group_sets", charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| + create_table "group_sets", charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t| t.bigint "unit_id" t.string "name" t.boolean "allow_students_to_create_groups", default: true @@ -85,7 +85,7 @@ t.index ["unit_id"], name: "index_group_sets_on_unit_id" end - create_table "group_submissions", charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| + create_table "group_submissions", charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t| t.bigint "group_id" t.string "notes" t.bigint "submitted_by_project_id" @@ -97,7 +97,7 @@ t.index ["task_definition_id"], name: "index_group_submissions_on_task_definition_id" end - create_table "groups", charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| + create_table "groups", charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t| t.bigint "group_set_id" t.bigint "tutorial_id" t.string "name" @@ -109,7 +109,7 @@ t.index ["tutorial_id"], name: "index_groups_on_tutorial_id" end - create_table "learning_outcome_task_links", charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| + create_table "learning_outcome_task_links", charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t| t.text "description" t.integer "rating" t.bigint "task_definition_id" @@ -122,7 +122,7 @@ t.index ["task_id"], name: "index_learning_outcome_task_links_on_task_id" end - create_table "learning_outcomes", charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| + create_table "learning_outcomes", charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t| t.bigint "unit_id" t.integer "ilo_number" t.string "name" @@ -131,7 +131,7 @@ t.index ["unit_id"], name: "index_learning_outcomes_on_unit_id" end - create_table "logins", charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| + create_table "logins", charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t| t.datetime "timestamp" t.bigint "user_id" t.datetime "created_at", null: false @@ -139,7 +139,7 @@ t.index ["user_id"], name: "index_logins_on_user_id" end - create_table "overseer_assessments", charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| + create_table "overseer_assessments", charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t| t.bigint "task_id", null: false t.string "submission_timestamp", null: false t.string "result_task_status" @@ -150,7 +150,7 @@ t.index ["task_id"], name: "index_overseer_assessments_on_task_id" end - create_table "overseer_images", charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| + create_table "overseer_images", charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t| t.string "name", null: false t.string "tag", null: false t.datetime "created_at", null: false @@ -160,7 +160,7 @@ t.datetime "last_pulled_date" end - create_table "projects", charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| + create_table "projects", charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t| t.bigint "unit_id" t.string "project_role" t.datetime "created_at", null: false @@ -187,14 +187,14 @@ t.index ["user_id"], name: "index_projects_on_user_id" end - create_table "roles", charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| + create_table "roles", charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t| t.string "name" t.text "description" t.datetime "created_at", null: false t.datetime "updated_at", null: false end - create_table "task_comments", charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| + create_table "task_comments", charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t| t.bigint "task_id", null: false t.bigint "user_id", null: false t.string "comment", limit: 4096 @@ -225,7 +225,7 @@ t.index ["user_id"], name: "index_task_comments_on_user_id" end - create_table "task_definitions", charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| + create_table "task_definitions", charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t| t.bigint "unit_id" t.string "name" t.string "description", limit: 4096 @@ -256,7 +256,7 @@ t.index ["unit_id"], name: "index_task_definitions_on_unit_id" end - create_table "task_engagements", charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| + create_table "task_engagements", charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t| t.datetime "engagement_time" t.string "engagement" t.bigint "task_id" @@ -265,7 +265,7 @@ t.index ["task_id"], name: "index_task_engagements_on_task_id" end - create_table "task_pins", charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| + create_table "task_pins", charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t| t.bigint "task_id", null: false t.bigint "user_id", null: false t.datetime "created_at", null: false @@ -275,7 +275,7 @@ t.index ["user_id"], name: "fk_rails_915df186ed" end - create_table "task_similarities", charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| + create_table "task_similarities", charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t| t.bigint "task_id" t.bigint "other_task_id" t.integer "pct" @@ -290,14 +290,14 @@ t.index ["tii_submission_id"], name: "index_task_similarities_on_tii_submission_id" end - create_table "task_statuses", charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| + create_table "task_statuses", charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t| t.string "name" t.string "description" t.datetime "created_at", null: false t.datetime "updated_at", null: false end - create_table "task_submissions", charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| + create_table "task_submissions", charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t| t.datetime "submission_time" t.datetime "assessment_time" t.string "outcome" @@ -309,7 +309,7 @@ t.index ["task_id"], name: "index_task_submissions_on_task_id" end - create_table "tasks", charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| + create_table "tasks", charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t| t.bigint "task_definition_id" t.bigint "project_id" t.bigint "task_status_id" @@ -335,7 +335,7 @@ t.index ["task_status_id"], name: "index_tasks_on_task_status_id" end - create_table "teaching_periods", charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| + create_table "teaching_periods", charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t| t.string "period", null: false t.datetime "start_date", null: false t.datetime "end_date", null: false @@ -394,7 +394,7 @@ t.index ["tii_task_similarity_id"], name: "index_tii_submissions_on_tii_task_similarity_id" end - create_table "tutorial_enrolments", charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| + create_table "tutorial_enrolments", charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t| t.datetime "created_at", null: false t.datetime "updated_at", null: false t.bigint "project_id", null: false @@ -404,7 +404,7 @@ t.index ["tutorial_id"], name: "index_tutorial_enrolments_on_tutorial_id" end - create_table "tutorial_streams", charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| + create_table "tutorial_streams", charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t| t.string "name", null: false t.string "abbreviation", null: false t.datetime "created_at", null: false @@ -418,7 +418,7 @@ t.index ["unit_id"], name: "index_tutorial_streams_on_unit_id" end - create_table "tutorials", charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| + create_table "tutorials", charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t| t.bigint "unit_id" t.string "meeting_day" t.string "meeting_time" @@ -437,7 +437,7 @@ t.index ["unit_role_id"], name: "index_tutorials_on_unit_role_id" end - create_table "unit_roles", charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| + create_table "unit_roles", charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t| t.bigint "user_id" t.bigint "tutorial_id" t.datetime "created_at", null: false @@ -450,7 +450,7 @@ t.index ["user_id"], name: "index_unit_roles_on_user_id" end - create_table "units", charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| + create_table "units", charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t| t.string "name" t.string "description", limit: 4096 t.datetime "start_date" @@ -474,13 +474,16 @@ t.bigint "overseer_image_id" t.datetime "portfolio_auto_generation_date" t.string "tii_group_context_id" + t.integer "creditpoint" + t.string "prerequisite", default: "Nil" + t.string "corequisite", default: "Nil" t.index ["draft_task_definition_id"], name: "index_units_on_draft_task_definition_id" t.index ["main_convenor_id"], name: "index_units_on_main_convenor_id" t.index ["overseer_image_id"], name: "index_units_on_overseer_image_id" t.index ["teaching_period_id"], name: "index_units_on_teaching_period_id" end - create_table "users", charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| + create_table "users", charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t| t.string "email", default: "", null: false t.string "encrypted_password", default: "", null: false t.string "reset_password_token" @@ -513,7 +516,7 @@ t.index ["role_id"], name: "index_users_on_role_id" end - create_table "webcal_unit_exclusions", charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| + create_table "webcal_unit_exclusions", charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t| t.bigint "webcal_id", null: false t.bigint "unit_id", null: false t.index ["unit_id", "webcal_id"], name: "index_webcal_unit_exclusions_on_unit_id_and_webcal_id", unique: true @@ -521,7 +524,7 @@ t.index ["webcal_id"], name: "fk_rails_d5fab02cb7" end - create_table "webcals", charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| + create_table "webcals", charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t| t.string "guid", limit: 36, null: false t.boolean "include_start_dates", default: false, null: false t.bigint "user_id" diff --git a/lib/helpers/database_populator.rb b/lib/helpers/database_populator.rb index 1d197a60c..ce93f9807 100644 --- a/lib/helpers/database_populator.rb +++ b/lib/helpers/database_populator.rb @@ -216,7 +216,10 @@ def generate_units code: unit_details[:code], name: unit_details[:name], description: faker_random_sentence(10, 15), - teaching_period: unit_details[:teaching_period] + teaching_period: unit_details[:teaching_period], + creditpoint: unit_details[:creditpoint], + prerequisite: unit_details[:prerequisite], + corequisite: unit_details[:corequisite] } else data = { @@ -224,7 +227,10 @@ def generate_units name: unit_details[:name], description: faker_random_sentence(10, 15), start_date: Time.zone.now - 6.weeks, - end_date: 13.weeks.since(Time.zone.now - 6.weeks) + end_date: 13.weeks.since(Time.zone.now - 6.weeks), + creditpoint: unit_details[:creditpoint], + prerequisite: unit_details[:prerequisite], + corequisite: unit_details[:corequisite] } end @@ -336,7 +342,10 @@ def generate_fixed_data ], students: [], num_tasks: some_tasks, + creditpoint: Faker::Number.between(from: 0, to: 2), ilos: Faker::Number.between(from: 1, to: 3), + prerequisite: "SIT111", + corequisite: "Nil" }, oop: { code: "COS20007", @@ -349,7 +358,10 @@ def generate_fixed_data { user: :joostfunkekupper, num: few_tutorials }, ], num_tasks: many_tasks, + creditpoint: Faker::Number.between(from: 0, to: 2), ilos: Faker::Number.between(from: 0, to: 3), + prerequisite: "SIT102", + corequisite: "Nil", students: [:cliff] }, ai4g: { @@ -361,7 +373,10 @@ def generate_fixed_data { user: :cliff, num: few_tutorials }, ], num_tasks: few_tasks, + creditpoint: Faker::Number.between(from: 0, to: 2), ilos: Faker::Number.between(from: 0, to: 3), + prerequisite: "SEJ104", + corequisite: "Nil", students: [:acummaudo] }, gameprog: { @@ -372,7 +387,10 @@ def generate_fixed_data { user: :aconvenor, num: few_tutorials }, ], num_tasks: few_tasks, + creditpoint: Faker::Number.between(from: 0, to: 2), ilos: Faker::Number.between(from: 0, to: 3), + prerequisite: "SIT210", + corequisite: "Nil", students: [:acain, :ajones] }, }