diff --git a/.circleci/config.yml b/.circleci/config.yml index b688ef660..76d849dc1 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -81,7 +81,7 @@ jobs: key: nokul-yarn-{{ checksum "yarn.lock" }} paths: - node_modules/ - rake_test: + test_suite: <<: *ruby_2_5_1 steps: - restore_cache: @@ -108,8 +108,20 @@ jobs: - run: bundle install - run: bin/yarn install - run: bundle exec rake quality:rails - - run: bundle exec rake security:all - run: bin/yarn run lint + security: + <<: *ruby_2_5_1 + steps: + - restore_cache: + <<: *repository + - restore_cache: + <<: *restore_bundle + - restore_cache: + <<: *restore_yarn + - run: bundle --path vendor/bundle --without development + - run: bundle install + - run: bin/yarn install + - run: bundle exec rake security:all deploy_develop: machine: enabled: true @@ -120,7 +132,7 @@ jobs: command: | git remote add develop dokku@app.omu.sh:nokul-develop && git push develop develop:master - deploy: + deploy_master: machine: enabled: true steps: @@ -143,21 +155,28 @@ workflows: - bundle_assets: requires: - bundle_dependencies - - rake_test: + - test_suite: requires: - bundle_assets - karma: requires: - bundle_assets + - security: + requires: + - bundle_assets - deploy_develop: requires: + - test_suite - karma + - security filters: branches: only: develop - - deploy: + - deploy_master: requires: + - test_suite - karma + - security filters: branches: only: master diff --git a/Gemfile.lock b/Gemfile.lock index ecd69693c..b8c1c41ca 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -44,15 +44,15 @@ GEM tzinfo (~> 1.1) addressable (2.5.2) public_suffix (>= 2.0.2, < 4.0) - ancestry (3.0.4) + ancestry (3.0.5) activerecord (>= 3.2.0) archive-zip (0.11.0) io-like (~> 0.3.0) arel (9.0.0) ast (2.4.0) aws-eventstream (1.0.1) - aws-partitions (1.107.0) - aws-sdk-core (3.36.0) + aws-partitions (1.110.0) + aws-sdk-core (3.37.0) aws-eventstream (~> 1.0) aws-partitions (~> 1.0) aws-sigv4 (~> 1.0) @@ -96,7 +96,7 @@ GEM codacy-coverage (2.1.0) simplecov coderay (1.1.2) - concurrent-ruby (1.1.1) + concurrent-ruby (1.1.3) connection_pool (2.2.2) crack (0.4.3) safe_yaml (~> 1.0.0) @@ -169,7 +169,7 @@ GEM nokogiri (1.8.5) mini_portile2 (~> 2.3.0) orm_adapter (0.5.0) - pagy (0.21.0) + pagy (0.22.0) parallel (1.12.1) parser (2.5.3.0) ast (~> 2.4.0) @@ -182,7 +182,7 @@ GEM pry (0.12.0) coderay (~> 1.1.0) method_source (~> 0.9.0) - pry-rails (0.3.6) + pry-rails (0.3.7) pry (>= 0.10.4) public_suffix (3.0.3) puma (3.12.0) @@ -253,7 +253,7 @@ GEM selenium-webdriver (3.141.0) childprocess (~> 0.5) rubyzip (~> 1.2, >= 1.2.2) - sidekiq (5.2.2) + sidekiq (5.2.3) connection_pool (~> 2.2, >= 2.2.2) rack-protection (>= 1.5.0) redis (>= 3.3.5, < 5) diff --git a/app/controllers/calendar/academic_terms_controller.rb b/app/controllers/calendar/academic_terms_controller.rb index fa43b1fcd..d60ba55f6 100644 --- a/app/controllers/calendar/academic_terms_controller.rb +++ b/app/controllers/calendar/academic_terms_controller.rb @@ -7,7 +7,7 @@ class AcademicTermsController < ApplicationController before_action :set_academic_term, only: %i[edit update destroy] def index - @academic_terms = pagy_by_search(AcademicTerm.order(:year)) + @academic_terms = pagy_by_search(AcademicTerm.order(:year, :term)) end def new @@ -40,7 +40,7 @@ def set_academic_term end def academic_term_params - params.require(:academic_term).permit(:year, :term) + params.require(:academic_term).permit(:year, :term, :start_of_term, :end_of_term, :active) end end end diff --git a/app/controllers/calendar/calendar_titles_controller.rb b/app/controllers/calendar/calendar_titles_controller.rb index 573f0780e..70f799a4d 100644 --- a/app/controllers/calendar/calendar_titles_controller.rb +++ b/app/controllers/calendar/calendar_titles_controller.rb @@ -40,7 +40,7 @@ def set_calendar_title end def calendar_title_params - params.require(:calendar_title).permit(:name) + params.require(:calendar_title).permit(:name, type_ids: []) end end end diff --git a/app/controllers/calendar/calendar_types_controller.rb b/app/controllers/calendar/calendar_types_controller.rb index 61b275a76..edefc8cf2 100644 --- a/app/controllers/calendar/calendar_types_controller.rb +++ b/app/controllers/calendar/calendar_types_controller.rb @@ -44,8 +44,7 @@ def set_calendar_type end def calendar_type_params - params.require(:calendar_type) - .permit(:name, calendar_title_types_attributes: %i[id type_id title_id status _destroy]) + params.require(:calendar_type).permit(:name) end end end diff --git a/app/controllers/course_management/curriculum_semester_courses_controller.rb b/app/controllers/course_management/curriculum_semester_courses_controller.rb new file mode 100644 index 000000000..8a262dcd1 --- /dev/null +++ b/app/controllers/course_management/curriculum_semester_courses_controller.rb @@ -0,0 +1,46 @@ +# frozen_string_literal: true + +module CourseManagement + class CurriculumSemesterCoursesController < ApplicationController + before_action :set_semester, only: %i[new create edit update destroy] + before_action :set_semester_course, only: %i[edit update destroy] + + def new + @semester_course = @semester.curriculum_semester_courses.new + end + + def edit; end + + def create + @semester_course = @semester.curriculum_semester_courses.new(semester_course_params) + @semester_course.save ? redirect_with('success') : render(:new) + end + + def update + @semester_course.update(semester_course_params) ? redirect_with('success') : render(:edit) + end + + def destroy + message = @semester_course.destroy ? 'success' : 'error' + redirect_with(message) + end + + private + + def redirect_with(message) + redirect_to curriculum_path(@semester.curriculum), flash: { notice: t(".#{message}") } + end + + def set_semester_course + @semester_course = @semester.curriculum_semester_courses.find(params[:id]) + end + + def set_semester + @semester = CurriculumSemester.find(params[:curriculum_semester_id]) + end + + def semester_course_params + params.require(:curriculum_semester_course).permit(:course_id, :ects) + end + end +end diff --git a/app/controllers/course_management/curriculums_controller.rb b/app/controllers/course_management/curriculums_controller.rb index ee2262754..066a5c138 100644 --- a/app/controllers/course_management/curriculums_controller.rb +++ b/app/controllers/course_management/curriculums_controller.rb @@ -13,7 +13,11 @@ def index @pagy, @curriculums = pagy(curriculums) end - def show; end + def show + @semesters = @curriculum.semesters.includes( + curriculum_semester_courses: :course + ) + end def new @curriculum = Curriculum.new @@ -46,7 +50,10 @@ def set_curriculum end def curriculum_params - params.require(:curriculum).permit(:name, :unit_id, :number_of_semesters, :status, program_ids: []) + params.require(:curriculum).permit( + :name, :unit_id, :status, program_ids: [], + semesters_attributes: %i[id name sequence _destroy] + ) end end end diff --git a/app/models/academic_calendar.rb b/app/models/academic_calendar.rb index 3d451f891..770217e2d 100644 --- a/app/models/academic_calendar.rb +++ b/app/models/academic_calendar.rb @@ -24,4 +24,7 @@ class AcademicCalendar < ApplicationRecord # delegates delegate :name, to: :calendar_type, prefix: :type + + # scopes + scope :active, -> { joins(:academic_term).merge(AcademicTerm.where(active: true)) } end diff --git a/app/models/academic_term.rb b/app/models/academic_term.rb index 61ac594ae..3cbfd2f4b 100644 --- a/app/models/academic_term.rb +++ b/app/models/academic_term.rb @@ -3,10 +3,13 @@ class AcademicTerm < ApplicationRecord # relations has_many :academic_calendars, dependent: :nullify + has_many :calendar_events, through: :academic_calendars # validations validates :term, presence: true validates :year, presence: true, uniqueness: { scope: :term } + validates :start_of_term, presence: true + validates :end_of_term, presence: true # enums enum term: { fall: 0, spring: 1, summer: 2 } diff --git a/app/models/calendar_event.rb b/app/models/calendar_event.rb index 352ab6f3f..becb94647 100644 --- a/app/models/calendar_event.rb +++ b/app/models/calendar_event.rb @@ -4,6 +4,7 @@ class CalendarEvent < ApplicationRecord # relations belongs_to :academic_calendar belongs_to :calendar_title + has_one :term, through: :academic_calendar, source: :academic_term # validations validates :start_date, presence: true diff --git a/app/models/calendar_type.rb b/app/models/calendar_type.rb index 204292a24..c8ece20e5 100644 --- a/app/models/calendar_type.rb +++ b/app/models/calendar_type.rb @@ -5,7 +5,6 @@ class CalendarType < ApplicationRecord has_many :calendar_title_types, foreign_key: :type_id, inverse_of: :type, dependent: :destroy has_many :titles, through: :calendar_title_types has_many :academic_calendars, dependent: :destroy - accepts_nested_attributes_for :calendar_title_types, reject_if: :all_blank, allow_destroy: true # validations validates :name, presence: true, uniqueness: true diff --git a/app/models/curriculum.rb b/app/models/curriculum.rb index 7eeb10ce2..d41d56426 100644 --- a/app/models/curriculum.rb +++ b/app/models/curriculum.rb @@ -5,8 +5,6 @@ class Curriculum < ApplicationRecord include PgSearch include DynamicSearch - MAX_NUMBER_OF_SEMESTERS = 12 - pg_search_scope( :search, against: %i[name], @@ -20,12 +18,16 @@ class Curriculum < ApplicationRecord belongs_to :unit has_many :unit_curriculums, dependent: :destroy has_many :programs, through: :unit_curriculums, source: :unit + has_many :semesters, class_name: 'CurriculumSemester', + inverse_of: :curriculum, dependent: :destroy + has_many :courses, through: :semesters + + # nested models + accepts_nested_attributes_for :semesters, reject_if: :all_blank, allow_destroy: true # validations validates :name, presence: true, uniqueness: { scope: :unit_id } - validates :number_of_semesters, numericality: { - greater_than: 0, less_than_or_equal_to: MAX_NUMBER_OF_SEMESTERS - } + validates :semesters_count, numericality: { greater_than_or_equal_to: 0 } validates :status, presence: true # enumerations diff --git a/app/models/curriculum_semester.rb b/app/models/curriculum_semester.rb new file mode 100644 index 000000000..aa8e954ab --- /dev/null +++ b/app/models/curriculum_semester.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +class CurriculumSemester < ApplicationRecord + # relations + has_many :curriculum_semester_courses, dependent: :destroy + has_many :courses, through: :curriculum_semester_courses + belongs_to :curriculum, counter_cache: :semesters_count, inverse_of: :semesters + + # validations + validates :name, presence: true, uniqueness: { scope: :curriculum_id } + validates :sequence, numericality: { greater_than: 0 }, uniqueness: { scope: :curriculum_id } + + # custom methods + def available_courses(add_courses: []) + courses = curriculum.unit.courses.active.where.not(id: curriculum.courses.ids) + add_courses.compact! + add_courses.present? ? (courses.to_a + add_courses) : courses + end +end diff --git a/app/models/curriculum_semester_course.rb b/app/models/curriculum_semester_course.rb new file mode 100644 index 000000000..ef0e5ebc8 --- /dev/null +++ b/app/models/curriculum_semester_course.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +class CurriculumSemesterCourse < ApplicationRecord + # relations + belongs_to :course + belongs_to :curriculum_semester + + # validations + validates :ects, presence: true, numericality: { greater_than: 0 } + + # delegates + delegate :code, :credit, :name, to: :course +end diff --git a/app/services/xokul/connection.rb b/app/services/xokul/connection.rb index 612cfa1d3..9ec110244 100644 --- a/app/services/xokul/connection.rb +++ b/app/services/xokul/connection.rb @@ -8,16 +8,19 @@ module Connection private_constant :BASE_URL, :BEARER_TOKEN # rubocop:disable Metrics/MethodLength - def self.request(path, params: {}) + def self.request(path, params: {}, **http_options) + http_options[:open_timeout] ||= http_options[:read_timeout] ||= 5 if Rails.env.test? + response = RestClient.get( URI.join(BASE_URL, path).to_s, headers: { - Authorization: "Bearer #{BEARER_TOKEN}", - 'Content-Type': 'application/json' + 'Authorization' => "Bearer #{BEARER_TOKEN}", + 'Content-Type' => 'application/json' }, payload: params.to_json, use_ssl: true, - verify_mode: OpenSSL::SSL::VERIFY_PEER + verify_mode: OpenSSL::SSL::VERIFY_PEER, + **http_options ) response.error! diff --git a/app/services/xokul/yoksis/staff.rb b/app/services/xokul/yoksis/staff.rb index 1dbe137af..5daab4de7 100644 --- a/app/services/xokul/yoksis/staff.rb +++ b/app/services/xokul/yoksis/staff.rb @@ -16,7 +16,10 @@ def nationalities end def pages(page:) - Connection.request '/yoksis/staff/pages', params: { page: page } + Connection.request( + '/yoksis/staff/pages', + params: { page: page }, read_timeout: 15 + ) end def total_pages diff --git a/app/services/xokul/yoksis/units.rb b/app/services/xokul/yoksis/units.rb index 393673214..b2a22ee92 100644 --- a/app/services/xokul/yoksis/units.rb +++ b/app/services/xokul/yoksis/units.rb @@ -7,7 +7,8 @@ module Units def changes(day:, month:, year:) Connection.request( - '/yoksis/units/changes', params: { day: day, month: month, year: year } + '/yoksis/units/changes', + params: { day: day, month: month, year: year }, read_timeout: 10 ) end diff --git a/app/views/account/employees/_form.html.erb b/app/views/account/employees/_form.html.erb index 80ad81fd8..2e7261bd9 100644 --- a/app/views/account/employees/_form.html.erb +++ b/app/views/account/employees/_form.html.erb @@ -17,7 +17,7 @@ label_method: lambda { |title| title.name + ' - ' + title.branch } %>
- <%= f.input :active %> + <%= f.input :active, label: t('active') %>
<%= f.button :submit, class: 'btn btn-outline-success btn-sm' %> diff --git a/app/views/calendar/academic_calendars/show.html.erb b/app/views/calendar/academic_calendars/show.html.erb index a49621f01..3b4b0cf3d 100644 --- a/app/views/calendar/academic_calendars/show.html.erb +++ b/app/views/calendar/academic_calendars/show.html.erb @@ -42,13 +42,22 @@
- <% @events.each do |event| %> + - - - + + + - <% end %> + + + <% @events.each do |event| %> + + + + + + <% end %> +
<%= event.calendar_title_name %><%= event.start_date.strftime('%F %T') %><%= event.end_date.try(:strftime, '%F %T') %><%= t('.event_title') %><%= t('.event_start_date') %><%= t('.event_end_date') %>
<%= event.calendar_title_name %><%= event.start_date.strftime('%F %T') %><%= event.end_date.try(:strftime, '%F %T') %>
diff --git a/app/views/calendar/academic_terms/_form.html.erb b/app/views/calendar/academic_terms/_form.html.erb index 8bc994242..e0ff59694 100644 --- a/app/views/calendar/academic_terms/_form.html.erb +++ b/app/views/calendar/academic_terms/_form.html.erb @@ -17,6 +17,15 @@
<%= f.input :term, collection: enum_options_for_select(f.object.class, :term) %>
+
+ <%= f.input :start_of_term, start_year: 2005 %> +
+
+ <%= f.input :end_of_term, start_year: 2005 %> +
+
+ <%= f.input :active %> +
<%= f.button :submit, class: 'btn btn-outline-success btn-sm' %> <%= link_to_back(:back) %> diff --git a/app/views/calendar/academic_terms/index.html.erb b/app/views/calendar/academic_terms/index.html.erb index b5275d640..55d6f4cad 100644 --- a/app/views/calendar/academic_terms/index.html.erb +++ b/app/views/calendar/academic_terms/index.html.erb @@ -14,6 +14,9 @@ <%= t('.year') %> <%= t('.term') %> + <%= t('.start_of_term') %> + <%= t('.end_of_term') %> + <%= t('.active') %> <%= t('actions') %> @@ -22,6 +25,9 @@ <%= academic_term.year %> <%= enum_t(academic_term, :term) %> + <%= academic_term.start_of_term.try(:strftime, '%F %T') %> + <%= academic_term.end_of_term.try(:strftime, '%F %T') %> + <%= academic_term.active? ? t('active') : t('passive') %> <%= link_to_edit(edit_academic_term_path(academic_term)) %> <%= link_to_destroy(academic_term) %> diff --git a/app/views/calendar/calendar_titles/_form.html.erb b/app/views/calendar/calendar_titles/_form.html.erb index db1f4e4a0..2b5a0285d 100644 --- a/app/views/calendar/calendar_titles/_form.html.erb +++ b/app/views/calendar/calendar_titles/_form.html.erb @@ -15,6 +15,9 @@
<%= f.input :name %>
+
+ <%= f.association :types, as: :check_boxes %> +
<%= f.button :submit, class: 'btn btn-outline-success btn-sm' %> <%= link_to_back(:back) %> diff --git a/app/views/calendar/calendar_types/_calendar_title_type_fields.erb b/app/views/calendar/calendar_types/_calendar_title_type_fields.erb deleted file mode 100644 index 45db9920a..000000000 --- a/app/views/calendar/calendar_types/_calendar_title_type_fields.erb +++ /dev/null @@ -1,11 +0,0 @@ -
-
-
- <%= f.association :title, collection: CalendarTitle.all %> - <%= f.input :status, collection: enum_options_for_select(f.object.class, :status) %> -
- -
-
diff --git a/app/views/calendar/calendar_types/_form.html.erb b/app/views/calendar/calendar_types/_form.html.erb index 33703d98c..46c90a754 100644 --- a/app/views/calendar/calendar_types/_form.html.erb +++ b/app/views/calendar/calendar_types/_form.html.erb @@ -20,20 +20,8 @@ <%= link_to_back(:back) %>
-
-

<%= t('.titles') %>

-
- <%= f.simple_fields_for :calendar_title_types do |title| %> - <%= render "calendar_title_type_fields", f: title %> - <% end %> -
- <%= link_to_add_association t('.new_title_link'), f, :calendar_title_types, class: 'btn btn-outline-primary btn-sm' %> -
- <% end %> - -<%= javascript_include_tag 'shared/cocoon' %> \ No newline at end of file diff --git a/app/views/calendar/calendar_types/show.html.erb b/app/views/calendar/calendar_types/show.html.erb index 88c32dad8..56451397a 100644 --- a/app/views/calendar/calendar_types/show.html.erb +++ b/app/views/calendar/calendar_types/show.html.erb @@ -1,5 +1,5 @@
- <%= link_to_back(:back) %> + <%= link_to_back calendar_types_path %>
@@ -12,7 +12,7 @@ - + diff --git a/app/views/course_management/curriculum_semester_courses/_form.html.erb b/app/views/course_management/curriculum_semester_courses/_form.html.erb new file mode 100644 index 000000000..09c564e2a --- /dev/null +++ b/app/views/course_management/curriculum_semester_courses/_form.html.erb @@ -0,0 +1,30 @@ +
+
+
+
+ <%= fa_icon 'book' %> + <%= form_title %> +
+
+ <%= simple_form_for([@semester, @semester_course]) do |f| %> + <%= f.error_notification %> +
+
+ <%= f.association :course, collection: @semester.available_courses(add_courses: [@semester_course.course]) %> +
+
+ <%= f.input :ects %> +
+
+ +
+
+ <%= f.button :submit, class: 'btn btn-outline-success btn-sm' %> + <%= link_to_back(:back) %> +
+
+ <% end %> +
+
+
+
\ No newline at end of file diff --git a/app/views/course_management/curriculum_semester_courses/edit.html.erb b/app/views/course_management/curriculum_semester_courses/edit.html.erb new file mode 100644 index 000000000..b84819a40 --- /dev/null +++ b/app/views/course_management/curriculum_semester_courses/edit.html.erb @@ -0,0 +1 @@ +<%= render 'form', semester_course: @semester_course, form_title: t('.form_title') %> diff --git a/app/views/course_management/curriculum_semester_courses/new.html.erb b/app/views/course_management/curriculum_semester_courses/new.html.erb new file mode 100644 index 000000000..b84819a40 --- /dev/null +++ b/app/views/course_management/curriculum_semester_courses/new.html.erb @@ -0,0 +1 @@ +<%= render 'form', semester_course: @semester_course, form_title: t('.form_title') %> diff --git a/app/views/course_management/curriculums/_form.html.erb b/app/views/course_management/curriculums/_form.html.erb index d7606ae9b..49f6148af 100644 --- a/app/views/course_management/curriculums/_form.html.erb +++ b/app/views/course_management/curriculums/_form.html.erb @@ -12,9 +12,6 @@
<%= f.input :name %>
-
- <%= f.input :number_of_semesters, collection: (2..Curriculum::MAX_NUMBER_OF_SEMESTERS) %> -
<%= f.association :unit, collection: Unit.active.curriculumable %>
@@ -26,6 +23,19 @@ <%= f.input :status, collection: enum_options_for_select(f.object.class, :status) %> + + +

<%= t('.semesters') %>

+
+ <%= f.simple_fields_for :semesters do |semester| %> + <%= render 'semester_fields', f: semester %> + <% end %> + +
+ +
<%= f.button :submit, class: 'btn btn-outline-success btn-sm' %> <%= link_to_back(:back) %> @@ -37,4 +47,5 @@
-<%= render 'select2' %> \ No newline at end of file +<%= render 'select2' %> +<%= javascript_include_tag 'shared/cocoon' %> \ No newline at end of file diff --git a/app/views/course_management/curriculums/_semester_fields.html.erb b/app/views/course_management/curriculums/_semester_fields.html.erb new file mode 100644 index 000000000..e16005327 --- /dev/null +++ b/app/views/course_management/curriculums/_semester_fields.html.erb @@ -0,0 +1,19 @@ +
+
+
+
+
+
+ <%= f.input :name %> +
+
+ <%= f.input :sequence %> +
+
+
+ +
+
+
\ No newline at end of file diff --git a/app/views/course_management/curriculums/_semesters.html.erb b/app/views/course_management/curriculums/_semesters.html.erb new file mode 100644 index 000000000..b880e1165 --- /dev/null +++ b/app/views/course_management/curriculums/_semesters.html.erb @@ -0,0 +1,49 @@ +
+ <% semesters.each do |semester| %> +
+
+
+ <%= fa_icon 'book' %><%= "#{semester.name} (#{semester.sequence})" %> +
+
+
<%= t('.name') %><%= t('.calendar_titles') %>
+ + + + + + + + + + + <% semester.curriculum_semester_courses.each do |semester_course| %> + + + + + + + + <% end %> + +
<%= t('.course.name') %><%= t('.course.code') %><%= t('.course.credit') %><%= t('.course.ects') %><%= t('actions') %>
<%= semester_course.name %><%= semester_course.code %><%= semester_course.credit %><%= semester_course.ects %> + <%= link_to_edit edit_curriculum_semester_curriculum_semester_course_path(semester, semester_course) %> + <%= link_to_destroy [semester, semester_course] %> +
+ +
+ <%= link_to_new new_curriculum_semester_curriculum_semester_course_path(semester) %> +
+
+ + + + + <% end %> + \ No newline at end of file diff --git a/app/views/course_management/curriculums/index.html.erb b/app/views/course_management/curriculums/index.html.erb index cf8756edb..c57df013a 100644 --- a/app/views/course_management/curriculums/index.html.erb +++ b/app/views/course_management/curriculums/index.html.erb @@ -14,7 +14,7 @@ <%= t('.name') %> <%= t('.unit') %> - <%= t('.number_of_semesters') %> + <%= t('.semesters_count') %> <%= t('.status') %> <%= t('actions') %> @@ -24,7 +24,7 @@ <%= link_to curriculum.name, curriculum %> <%= curriculum.unit.try(:name) %> - <%= curriculum.number_of_semesters %> + <%= curriculum.semesters_count %> <%= enum_t(curriculum, :status) %> <%= link_to_show curriculum %> diff --git a/app/views/course_management/curriculums/show.html.erb b/app/views/course_management/curriculums/show.html.erb index 1fb76d29e..c4e833136 100644 --- a/app/views/course_management/curriculums/show.html.erb +++ b/app/views/course_management/curriculums/show.html.erb @@ -21,8 +21,8 @@ <%= @curriculum.unit.try(:name) %> - <%= t('.number_of_semesters') %> - <%= @curriculum.number_of_semesters %> + <%= t('.semesters_count') %> + <%= @curriculum.semesters_count %> <%= t('.status') %> @@ -44,3 +44,5 @@ + +<%= render 'semesters', semesters: @semesters %> diff --git a/config/locales/defaults/en.yml b/config/locales/defaults/en.yml index 2eb50a5b2..42f70f1d0 100644 --- a/config/locales/defaults/en.yml +++ b/config/locales/defaults/en.yml @@ -9,14 +9,21 @@ en: show: Show update: Update actions: Actions + active: Active are_you_sure: Are you sure? created_at: Created At detailed_search: Detailed Search home_nav: Home 'no': 'No' + passive: Passive reset: Reset save: Save search: Search smart_search: Smart Search updated_at: Updated At 'yes': 'Yes' + + cocoon: + defaults: + add: 'Add' + remove: 'Remove' \ No newline at end of file diff --git a/config/locales/defaults/tr.yml b/config/locales/defaults/tr.yml index f68a66def..79f197d1b 100644 --- a/config/locales/defaults/tr.yml +++ b/config/locales/defaults/tr.yml @@ -9,14 +9,21 @@ tr: show: Görüntüle update: Güncelle actions: İşlemler + active: Aktif are_you_sure: Emin misiniz? created_at: Oluşturulma Tarihi detailed_search: Detaylı Arama home_nav: Anasayfa 'no': Hayır + passive: Pasif reset: Reset save: Kaydet search: Arama Yap smart_search: Akıllı Arama updated_at: Güncellenme Tarihi 'yes': Evet + + cocoon: + defaults: + add: 'Ekle' + remove: 'Sil' \ No newline at end of file diff --git a/config/locales/models/account/en.yml b/config/locales/models/account/en.yml index 5274524b5..11a9e7ff6 100644 --- a/config/locales/models/account/en.yml +++ b/config/locales/models/account/en.yml @@ -68,6 +68,7 @@ en: title_id: Title user_id: User position: + duty_id: Administrative Unit administrative_function_id: Administrative Function end_date: End Date start_date: Start Date diff --git a/config/locales/models/account/tr.yml b/config/locales/models/account/tr.yml index 027d28799..2485f6ef6 100644 --- a/config/locales/models/account/tr.yml +++ b/config/locales/models/account/tr.yml @@ -68,7 +68,8 @@ tr: title_id: Ünvan user_id: Kullanıcı position: - administrative_function_id: Görev + duty_id: İdari Birim + administrative_function_id: İdari Görev end_date: Bitiş Tarihi start_date: Başlangıç Tarihi helpers: diff --git a/config/locales/models/calendars/en.yml b/config/locales/models/calendars/en.yml index b005ceb9a..e9c7fc71a 100644 --- a/config/locales/models/calendars/en.yml +++ b/config/locales/models/calendars/en.yml @@ -9,6 +9,9 @@ en: senate_decision_date: Senate Decision Date senate_decision_no: Senate Decision No academic_term: &academic_term_attributes + active: Active Status + end_of_term: End of Term + start_of_term: Start of Term term: Term year: Year calendar_event: @@ -17,6 +20,7 @@ en: start_date: Date of Start calendar_title: &calendar_title_attributes name: Calendar Title + types: Calendar Types calendar_title_type: status: Status title: Title @@ -29,10 +33,6 @@ en: fall: Fall spring: Spring summer: Summer - calendar_title_type: - statuses: - active: Active - passive: Passive calendar: academic_calendars: calendar_event_fields: @@ -56,6 +56,9 @@ en: show: <<: *academic_calendar_attributes alert: Record could not be found! + event_end_date: Event End Date + event_start_date: Event Start Date + event_title: Event Title update: success: Academic calendar successfully updated. academic_terms: @@ -102,7 +105,6 @@ en: form_title: Update the Calendar Type form: new_title_link: New Calendar Title - titles: Calendar Titles index: <<: *calendar_type_attributes card_header: Calendar Types @@ -112,6 +114,7 @@ en: show: <<: *calendar_type_attributes card_header: '%{calendar_type} Calendar Type' + calendar_titles: Calendar Titles update: success: Calendar type successfully updated. helpers: diff --git a/config/locales/models/calendars/tr.yml b/config/locales/models/calendars/tr.yml index 6a36db72f..2a6b82bf6 100644 --- a/config/locales/models/calendars/tr.yml +++ b/config/locales/models/calendars/tr.yml @@ -9,6 +9,9 @@ tr: senate_decision_date: Senato Karar Tarihi senate_decision_no: Senato Karar No academic_term: &academic_term_attributes + active: Aktiflik Durumu + end_of_term: Dönem Sonu + start_of_term: Dönem Başlangıcı term: Akademik Dönem year: Akademik Yıl calendar_event: @@ -17,6 +20,7 @@ tr: start_date: Başlama Tarihi calendar_title: &calendar_title_attributes name: Takvim Başlığı + types: Takvim Türleri calendar_title_type: status: Durum title: Başlık @@ -29,10 +33,6 @@ tr: fall: Güz spring: Bahar summer: Yaz - calendar_title_type: - statuses: - active: Aktif - passive: Pasif calendar: academic_calendars: calendar_event_fields: @@ -56,6 +56,9 @@ tr: show: <<: *academic_calendar_attributes alert: Böyle bir kayıt bulunamadı! + event_end_date: Etkinlik Bitiş Tarihi + event_start_date: Etkinlik Başlama Tarihi + event_title: Etkinlik Başlığı update: success: Akademik takvim başarıyla güncellendi. academic_terms: @@ -102,7 +105,6 @@ tr: form_title: Takvim Türünü Güncelle form: new_title_link: Yeni Başlık Ekle - titles: Takvim Başlıkları index: <<: *calendar_type_attributes card_header: Takvim Türleri @@ -112,6 +114,7 @@ tr: show: <<: *calendar_type_attributes card_header: '%{calendar_type} Takvim Türü' + calendar_titles: Takvim Başlıkları update: success: Takvim türü başarıyla güncellendi. helpers: diff --git a/config/locales/models/course_management/en.yml b/config/locales/models/course_management/en.yml index c02c8dcc1..f39a2b857 100644 --- a/config/locales/models/course_management/en.yml +++ b/config/locales/models/course_management/en.yml @@ -12,6 +12,7 @@ en: status: Status theoric: Theoric unit: Unit + ects: Ects course_group_type: &course_group_type_attributes name: Course Group Type Name course_unit_group: &course_unit_group_attributes @@ -24,10 +25,16 @@ en: unit: Unit curriculum: &curriculum_attributes name: Curriculum Name - number_of_semesters: Number of Semesters + semesters_count: Number of Semesters programs: Programs status: Status unit: Unit + curriculum_semester: + name: Semester Name + sequence: Sequence + curriculum_semester_course: &curriculum_semester_course_attributes + course: Course + ects: ECTS enums: course: program_types: @@ -47,6 +54,7 @@ en: course_group_type: Course Group Type course_unit_group: Course Group curriculum: Curriculum + curriculum_semester_course: Curriculum Semester Course course_management: course_group_types: create: @@ -118,6 +126,8 @@ en: success: Curriculum successfully destroyed. edit: form_title: Update the Curriculum + form: + semesters: 'Semesters' index: <<: *curriculum_attributes add_new_curriculum: Add a New Curriculum @@ -127,13 +137,32 @@ en: search: smart_search_placeholder: Curriculum Name <<: *curriculum_attributes + semesters: + total_credits: 'Total Credits' + total_ects: 'Total ECTS' + course: + <<: *course_attributes show: <<: *curriculum_attributes update: success: Curriculum successfully updated. + curriculum_semester_courses: + create: + success: Curriculum semester course successfully created. + destroy: + error: An error occured when deleting the curriculum semester course. + success: Curriculum semester course successfully destroyed. + edit: + form_title: Update the Curriculum Semester Course + new: + form_title: Create a Curriculum Semester Course + update: + success: Curriculum semester course successfully updated. simple_form: labels: course: <<: *course_attributes curriculum: <<: *curriculum_attributes + curriculum_semester_course: + <<: *curriculum_semester_course_attributes \ No newline at end of file diff --git a/config/locales/models/course_management/tr.yml b/config/locales/models/course_management/tr.yml index 83064f7d2..e7f525037 100644 --- a/config/locales/models/course_management/tr.yml +++ b/config/locales/models/course_management/tr.yml @@ -12,6 +12,7 @@ tr: status: Durumu theoric: Teorik unit: Birim + ects: Ects course_group_type: &course_group_type_attributes name: Ders Grup Tür Adı course_unit_group: &course_unit_group_attributes @@ -24,10 +25,16 @@ tr: unit: Birim curriculum: &curriculum_attributes name: Müfredat Adı - number_of_semesters: Dönem Sayısı + semesters_count: Dönem Sayısı programs: Programlar status: Durumu unit: Birim + curriculum_semester: + name: Yarıyıl Adı + sequence: Sıra + curriculum_semester_course: &curriculum_semester_course_attributes + course: Ders + ects: AKTS enums: course: program_types: @@ -47,6 +54,7 @@ tr: course_group_type: Ders Grup Türü course_unit_group: Ders Grubu curriculum: Müfreadat + curriculum_semester_course: Müfreadat Yarıyıl Ders course_management: course_group_types: create: @@ -118,6 +126,8 @@ tr: success: Müfredat başarıyla silindi. edit: form_title: Müfredatı Düzenle + form: + semesters: 'Yarıyıllar' index: <<: *curriculum_attributes add_new_curriculum: Yeni Müfredat Ekle @@ -127,13 +137,32 @@ tr: search: smart_search_placeholder: Müfredat Adı <<: *curriculum_attributes + semesters: + total_credits: 'Toplam Kredi' + total_ects: 'Toplam ECTS' + course: + <<: *course_attributes show: <<: *curriculum_attributes update: success: Müfredat başarıyla güncellendi. + curriculum_semester_courses: + create: + success: Müfredat yarıyıl dersi başarıyla oluşturuldu. + destroy: + error: Müfredat yarıyıl dersi silinirken bir hata oluştu. + success: Müfredat yarıyıl dersi başarıyla silindi. + edit: + form_title: Müfredat Yarıyıl Dersi Düzenle + new: + form_title: Müfredat Yarıyıl Dersi Oluştur + update: + success: Müfredat yarıyıl dersi başarıyla güncellendi. simple_form: labels: course: <<: *course_attributes curriculum: <<: *curriculum_attributes + curriculum_semester_course: + <<: *curriculum_semester_course_attributes diff --git a/config/routes.rb b/config/routes.rb index 4fc1754bb..d60aa234d 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -11,6 +11,7 @@ draw :devise draw :account draw :calendar + draw :course_management draw :references draw :yoksis_references @@ -24,13 +25,6 @@ resources :documents - scope module: :course_management do - resources :courses - resources :course_unit_groups - resources :course_group_types, except: :show - resources :curriculums - end - scope module: :student_management do resources :prospective_students, only: %i[index show] do get 'register', on: :member diff --git a/config/routes/course_management.rb b/config/routes/course_management.rb new file mode 100644 index 000000000..b3694077e --- /dev/null +++ b/config/routes/course_management.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +scope module: :course_management do + resources :courses + resources :course_unit_groups + resources :course_group_types, except: :show + resources :curriculums + + resources :curriculum_semesters do + resources :curriculum_semester_courses + end +end diff --git a/db/migrate/20181019082622_create_curriculum_semesters.rb b/db/migrate/20181019082622_create_curriculum_semesters.rb new file mode 100644 index 000000000..15cfbb9b0 --- /dev/null +++ b/db/migrate/20181019082622_create_curriculum_semesters.rb @@ -0,0 +1,11 @@ +class CreateCurriculumSemesters < ActiveRecord::Migration[5.2] + def change + create_table :curriculum_semesters do |t| + t.string :name, null: false, limit: 255 + t.integer :sequence + t.references :curriculum, foreign_key: true + + t.timestamps + end + end +end diff --git a/db/migrate/20181019105705_rename_number_of_semesters_to_curriculum.rb b/db/migrate/20181019105705_rename_number_of_semesters_to_curriculum.rb new file mode 100644 index 000000000..3d028c920 --- /dev/null +++ b/db/migrate/20181019105705_rename_number_of_semesters_to_curriculum.rb @@ -0,0 +1,11 @@ +class RenameNumberOfSemestersToCurriculum < ActiveRecord::Migration[5.2] + def up + rename_column :curriculums, :number_of_semesters, :semesters_count + change_column :curriculums, :semesters_count, :integer, default: 0 + end + + def down + rename_column :curriculums, :semesters_count, :number_of_semesters + change_column :curriculums, :number_of_semesters, :integer, default: 0 + end +end diff --git a/db/migrate/20181107102430_create_curriculum_semester_courses.rb b/db/migrate/20181107102430_create_curriculum_semester_courses.rb new file mode 100644 index 000000000..1b5448b43 --- /dev/null +++ b/db/migrate/20181107102430_create_curriculum_semester_courses.rb @@ -0,0 +1,11 @@ +class CreateCurriculumSemesterCourses < ActiveRecord::Migration[5.2] + def change + create_table :curriculum_semester_courses do |t| + t.references :course, foreign_key: true + t.references :curriculum_semester, foreign_key: true + t.decimal :ects, precision: 5, scale: 2, default: 0, null: false + + t.timestamps + end + end +end diff --git a/db/migrate/20181107112324_add_start_term_and_end_term_to_academic_term.rb b/db/migrate/20181107112324_add_start_term_and_end_term_to_academic_term.rb new file mode 100644 index 000000000..d4a57e453 --- /dev/null +++ b/db/migrate/20181107112324_add_start_term_and_end_term_to_academic_term.rb @@ -0,0 +1,7 @@ +class AddStartTermAndEndTermToAcademicTerm < ActiveRecord::Migration[5.2] + def change + add_column :academic_terms, :start_of_term, :datetime + add_column :academic_terms, :end_of_term, :datetime + add_column :academic_terms, :active, :boolean, default: false + end +end diff --git a/db/schema.rb b/db/schema.rb index 7ba24ba5e..d4fe0f8a6 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.define(version: 2018_10_28_080308) do - +ActiveRecord::Schema.define(version: 2018_11_07_112324) do + # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -31,6 +31,9 @@ create_table "academic_terms", force: :cascade do |t| t.string "year", limit: 255, null: false t.integer "term", limit: 2, null: false + t.datetime "start_of_term" + t.datetime "end_of_term" + t.boolean "active", default: false end create_table "active_storage_attachments", force: :cascade do |t| @@ -251,9 +254,28 @@ t.index ["unit_id"], name: "index_courses_on_unit_id" end + create_table "curriculum_semester_courses", force: :cascade do |t| + t.bigint "course_id" + t.bigint "curriculum_semester_id" + t.decimal "ects", precision: 5, scale: 2, default: "0.0", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["course_id"], name: "index_curriculum_semester_courses_on_course_id" + t.index ["curriculum_semester_id"], name: "index_curriculum_semester_courses_on_curriculum_semester_id" + end + + create_table "curriculum_semesters", force: :cascade do |t| + t.string "name" + t.integer "sequence" + t.bigint "curriculum_id" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["curriculum_id"], name: "index_curriculum_semesters_on_curriculum_id" + end + create_table "curriculums", force: :cascade do |t| t.string "name", limit: 255 - t.integer "number_of_semesters" + t.integer "semesters_count", default: 0 t.integer "status", null: false t.bigint "unit_id" t.index ["unit_id"], name: "index_curriculums_on_unit_id" @@ -595,7 +617,7 @@ t.datetime "last_sign_in_at" t.inet "current_sign_in_ip" t.inet "last_sign_in_ip" - t.datetime "password_changed_at", default: -> { "CURRENT_TIMESTAMP" }, null: false + t.datetime "password_changed_at", default: -> { "now()" }, null: false t.string "slug", limit: 255 t.string "preferred_language", limit: 2, default: "tr" t.integer "articles_count", default: 0, null: false @@ -611,4 +633,7 @@ add_foreign_key "calendar_title_types", "calendar_titles", column: "title_id" add_foreign_key "calendar_title_types", "calendar_types", column: "type_id" add_foreign_key "courses", "languages" + add_foreign_key "curriculum_semester_courses", "courses" + add_foreign_key "curriculum_semester_courses", "curriculum_semesters" + add_foreign_key "curriculum_semesters", "curriculums" end diff --git a/lib/support/rest_client.rb b/lib/support/rest_client.rb index 9e3d7c160..a7b56092a 100644 --- a/lib/support/rest_client.rb +++ b/lib/support/rest_client.rb @@ -21,7 +21,8 @@ class UnsupportedHTTPOptionError < Error; end class Request SUPPORTED_HTTP_OPTIONS = { - open_timeout: nil, + open_timeout: 60, + read_timeout: 60, use_ssl: false, verify_mode: OpenSSL::SSL::VERIFY_NONE }.freeze diff --git a/test/controllers/calendar/academic_terms_controller_test.rb b/test/controllers/calendar/academic_terms_controller_test.rb index 7529e3795..9036d7498 100644 --- a/test/controllers/calendar/academic_terms_controller_test.rb +++ b/test/controllers/calendar/academic_terms_controller_test.rb @@ -23,7 +23,9 @@ class AcademicTermsControllerTest < ActionDispatch::IntegrationTest test 'should create academic term' do assert_difference('AcademicTerm.count') do post academic_terms_path, params: { - academic_term: { year: '2019 - 2020', term: :spring } + academic_term: { year: '2019 - 2020', term: :spring, + start_of_term: '2019-01-15 08:00:00'.in_time_zone, + end_of_term: '2019-06-18 17:00:00'.in_time_zone } } end @@ -31,6 +33,9 @@ class AcademicTermsControllerTest < ActionDispatch::IntegrationTest assert_equal '2019 - 2020', academic_term.year assert_equal 'spring', academic_term.term + assert_equal '2019-01-15 08:00:00'.in_time_zone, academic_term.start_of_term + assert_equal '2019-06-18 17:00:00'.in_time_zone, academic_term.end_of_term + assert_equal false, academic_term.active assert_redirected_to academic_terms_path assert_equal translate('.create.success'), flash[:notice] end diff --git a/test/controllers/calendar/calendar_types_controller_test.rb b/test/controllers/calendar/calendar_types_controller_test.rb index f11e6e226..6534ee728 100644 --- a/test/controllers/calendar/calendar_types_controller_test.rb +++ b/test/controllers/calendar/calendar_types_controller_test.rb @@ -29,11 +29,7 @@ class CalendarTypesControllerTest < ActionDispatch::IntegrationTest assert_difference('CalendarType.count') do post calendar_types_path, params: { calendar_type: { - name: 'Test Calendar Type', - calendar_title_types_attributes: { - 0 => { title_id: calendar_titles(:one).id, status: :active }, - 1 => { title_id: calendar_titles(:two).id, status: :active } - } + name: 'Test Calendar Type' } } end @@ -41,7 +37,6 @@ class CalendarTypesControllerTest < ActionDispatch::IntegrationTest calendar_type = CalendarType.last assert_equal 'Test Calendar Type', calendar_type.name - assert_equal 2, calendar_type.titles.count assert_redirected_to calendar_types_path assert_equal translate('.create.success'), flash[:notice] end diff --git a/test/controllers/course_management/curriculum_semester_course_controller_test.rb b/test/controllers/course_management/curriculum_semester_course_controller_test.rb new file mode 100644 index 000000000..1320c7729 --- /dev/null +++ b/test/controllers/course_management/curriculum_semester_course_controller_test.rb @@ -0,0 +1,84 @@ +# frozen_string_literal: true + +require 'test_helper' + +module CourseManagement + class CurriculumSemesterCourseControllerTest < ActionDispatch::IntegrationTest + setup do + sign_in users(:serhat) + @curriculum_semester = curriculum_semesters(:one) + @curriculum_semester_course = @curriculum_semester.curriculum_semester_courses.first + end + + test 'should get new' do + get new_curriculum_semester_curriculum_semester_course_path(@curriculum_semester) + assert_response :success + end + + test 'should create curriculum' do + course = @curriculum_semester.available_courses.first + assert_difference('CurriculumSemesterCourse.count') do + post curriculum_semester_curriculum_semester_courses_path( + @curriculum_semester + ), params: { + curriculum_semester_course: { + course_id: course.id, ects: 5 + } + } + end + + curriculum_semester_course = CurriculumSemesterCourse.last + + assert_equal course.name, curriculum_semester_course.name + assert_equal 5.0, curriculum_semester_course.ects + assert_redirected_to index_path + assert_equal translate('.create.success'), flash[:notice] + end + + test 'should get edit' do + get edit_curriculum_semester_curriculum_semester_course_path( + @curriculum_semester, @curriculum_semester_course + ) + assert_response :success + assert_select '.card-header strong', translate('.edit.form_title') + end + + test 'should update curriculum' do + curriculum_semester_course = CurriculumSemesterCourse.last + patch curriculum_semester_curriculum_semester_course_path( + @curriculum_semester, curriculum_semester_course + ), params: { + curriculum_semester_course: { + ects: 10 + } + } + + curriculum_semester_course.reload + + assert_equal 10, curriculum_semester_course.ects + assert_redirected_to index_path + assert_equal translate('.update.success'), flash[:notice] + end + + test 'should destroy curriculum' do + assert_difference('CurriculumSemesterCourse.count', -1) do + delete curriculum_semester_curriculum_semester_course_path( + @curriculum_semester, CurriculumSemesterCourse.last + ) + end + + assert_redirected_to index_path + assert_equal translate('.destroy.success'), flash[:notice] + end + + private + + def index_path + curriculum_path(@curriculum_semester.curriculum) + end + + def translate(key) + t("course_management.curriculum_semester_courses#{key}") + end + end +end diff --git a/test/controllers/course_management/curriculums_controller_test.rb b/test/controllers/course_management/curriculums_controller_test.rb index 48bd074c4..7f9a83454 100644 --- a/test/controllers/course_management/curriculums_controller_test.rb +++ b/test/controllers/course_management/curriculums_controller_test.rb @@ -31,7 +31,7 @@ class CurriculumsControllerTest < ActionDispatch::IntegrationTest assert_difference('Curriculum.count') do post index_path, params: { curriculum: { - name: 'Test Create Curriculum', unit_id: @unit.id, number_of_semesters: 4, status: :active + name: 'Test Create Curriculum', unit_id: @unit.id, status: :active } } end @@ -39,7 +39,6 @@ class CurriculumsControllerTest < ActionDispatch::IntegrationTest curriculum = Curriculum.last assert_equal 'Test Create Curriculum', curriculum.name - assert_equal 4, curriculum.number_of_semesters assert curriculum.active? assert_redirected_to index_path assert_equal translate('.create.success'), flash[:notice] @@ -55,14 +54,13 @@ class CurriculumsControllerTest < ActionDispatch::IntegrationTest curriculum = Curriculum.last patch curriculum_path(curriculum), params: { curriculum: { - name: 'Test Update Curriculum', number_of_semesters: 4, status: :passive + name: 'Test Update Curriculum', status: :passive } } curriculum.reload assert_equal 'Test Update Curriculum', curriculum.name - assert_equal 4, curriculum.number_of_semesters assert curriculum.passive? assert_redirected_to index_path assert_equal translate('.update.success'), flash[:notice] diff --git a/test/fixtures/academic_terms.yml b/test/fixtures/academic_terms.yml index 88990f517..237d5e901 100644 --- a/test/fixtures/academic_terms.yml +++ b/test/fixtures/academic_terms.yml @@ -1,23 +1,41 @@ fall_2017_2018: year: 2017 - 2018 term: fall + start_of_term: 2017-08-09 08:00:00 + end_of_term: 2017-12-18 17:00:00 + active: false spring_2017_2018: year: 2017 - 2018 term: spring + start_of_term: 2018-01-18 08:00:00 + end_of_term: 2018-06-18 17:00:00 + active: false summer_2017_2018: year: 2017 - 2018 term: summer + start_of_term: 2018-06-25 08:00:00 + end_of_term: 2018-07-20 17:00:00 + active: false fall_2018_2019: year: 2018 - 2019 term: fall + start_of_term: 2018-08-12 08:00:00 + end_of_term: 2018-12-18 17:00:00 + active: true spring_2018_2019: year: 2018 - 2019 term: spring + start_of_term: 2019-01-15 08:00:00 + end_of_term: 2019-06-18 17:00:00 + active: false summer_2018_2019: year: 2018 - 2019 term: summer + start_of_term: 2019-07-05 08:00:00 + end_of_term: 2019-08-13 17:00:00 + active: false diff --git a/test/fixtures/curriculum_semester_courses.yml b/test/fixtures/curriculum_semester_courses.yml new file mode 100644 index 000000000..631238314 --- /dev/null +++ b/test/fixtures/curriculum_semester_courses.yml @@ -0,0 +1,11 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +one: + course: ati + curriculum_semester: one + ects: 9.99 + +two: + course: ydi + curriculum_semester: two + ects: 9.99 diff --git a/test/fixtures/curriculum_semesters.yml b/test/fixtures/curriculum_semesters.yml new file mode 100644 index 000000000..edabcacba --- /dev/null +++ b/test/fixtures/curriculum_semesters.yml @@ -0,0 +1,14 @@ +one: + name: First Semester + sequence: 1 + curriculum: one + +two: + name: Second Semester + sequence: 2 + curriculum: one + +three: + name: First Semester + sequence: 1 + curriculum: two diff --git a/test/fixtures/curriculums.yml b/test/fixtures/curriculums.yml index 2bcbcf51f..ffdbb7534 100644 --- a/test/fixtures/curriculums.yml +++ b/test/fixtures/curriculums.yml @@ -1,11 +1,14 @@ one: name: Test Müfredatı 1 unit: omu - number_of_semesters: 8 status: active two: name: Test Müfredatı 2 unit: omu - number_of_semesters: 6 status: active + +three: + name: Test Müfredatı 3 + unit: omu + status: active \ No newline at end of file diff --git a/test/models/calendar/academic_term_test.rb b/test/models/calendar/academic_term_test.rb new file mode 100644 index 000000000..3ec3e9cfc --- /dev/null +++ b/test/models/calendar/academic_term_test.rb @@ -0,0 +1,52 @@ +# frozen_string_literal: true + +require 'test_helper' + +class AcademicTermTest < ActiveSupport::TestCase + setup do + @academic_term = academic_terms(:fall_2017_2018) + end + + # relations + %i[ + academic_calendars + calendar_events + ].each do |property| + test "a academic term can communicate with #{property}" do + assert @academic_term.send(property) + end + end + + # validations: presence + %i[ + year + term + start_of_term + end_of_term + ].each do |property| + test "presence validations for #{property} of a academic term" do + @academic_term.send("#{property}=", nil) + assert_not @academic_term.valid? + assert_not_empty @academic_term.errors[property] + end + end + + # validations: uniqueness + test 'academic term should be unique based on year' do + fake_term = @academic_term.dup + assert_not fake_term.valid? + assert_not_empty fake_term.errors[:year] + end + + # enums + { + term: { fall: 0, spring: 1, summer: 2 } + }.each do |property, hash| + hash.each do |key, value| + test "have a #{key} value of #{property} enum" do + enums = AcademicTerm.defined_enums.with_indifferent_access + assert_equal enums.dig(property, key), value + end + end + end +end diff --git a/test/models/calendar/calendar_event_test.rb b/test/models/calendar/calendar_event_test.rb index cdb043678..826cf2a27 100644 --- a/test/models/calendar/calendar_event_test.rb +++ b/test/models/calendar/calendar_event_test.rb @@ -3,26 +3,31 @@ require 'test_helper' class CalendarEventTest < ActiveSupport::TestCase + setup do + @calendar_events = calendar_events(:one) + end + # relations %i[ academic_calendar calendar_title + term ].each do |property| test "a calendar event can communicate with #{property}" do - assert calendar_events(:one).send(property) + assert @calendar_events.send(property) end end # validations: presence test 'should not save without start_date' do - calendar_events(:one).start_date = nil - assert_not calendar_events(:one).valid? - assert_not_empty calendar_events(:one).errors[:start_date] + @calendar_events.start_date = nil + assert_not @calendar_events.valid? + assert_not_empty @calendar_events.errors[:start_date] end # validations: uniqueness test 'event should be unique' do - fake_event = calendar_events(:one).dup + fake_event = @calendar_events.dup assert_not fake_event.valid? assert_not_empty fake_event.errors[:academic_calendar] end diff --git a/test/models/course/curriculum_semester_course_test.rb b/test/models/course/curriculum_semester_course_test.rb new file mode 100644 index 000000000..6f78a0e8b --- /dev/null +++ b/test/models/course/curriculum_semester_course_test.rb @@ -0,0 +1,39 @@ +# frozen_string_literal: true + +require 'test_helper' + +class CurriculumSemesterCourseTest < ActiveSupport::TestCase + setup do + @semester_course = curriculum_semester_courses(:one) + end + + # relations + %i[ + course + curriculum_semester + ].each do |relation| + test "curriculum semester course can communicate with #{relation}" do + assert @semester_course.send(relation) + end + end + + # validations: presence + { + course_id: :course, + curriculum_semester_id: :curriculum_semester, + ects: :ects + }.each do |property, error_message_key| + test "presence validations for #{property} of a curriculum semester course" do + @semester_course.send("#{property}=", nil) + assert_not @semester_course.valid? + assert_not_empty @semester_course.errors[error_message_key] + end + end + + # validations: numericality + test 'numericality validations for ects of a curriculum semester course' do + @semester_course.ects = 0 + assert_not @semester_course.valid? + assert_not_empty @semester_course.errors[:ects] + end +end diff --git a/test/models/course/curriculum_semester_test.rb b/test/models/course/curriculum_semester_test.rb new file mode 100644 index 000000000..e91df52a3 --- /dev/null +++ b/test/models/course/curriculum_semester_test.rb @@ -0,0 +1,62 @@ +# frozen_string_literal: true + +require 'test_helper' + +class CurriculumSemesterTest < ActiveSupport::TestCase + setup do + @semester = curriculum_semesters(:one) + end + + # relations + %i[ + courses + curriculum + curriculum_semester_courses + ].each do |relation| + test "curriculum semester can communicate with #{relation}" do + assert @semester.send(relation) + end + end + + # validations: presence + %i[ + name + sequence + ].each do |property| + test "presence validations for #{property} of a curriculum semester" do + @semester.send("#{property}=", nil) + assert_not @semester.valid? + assert_not_empty @semester.errors[property] + end + end + + # validations: uniqueness + test 'uniqueness validations for name of a curriculum semester' do + fake = @semester.dup + assert_not fake.valid? + assert_not_empty fake.errors[:name] + + fake.curriculum_id = curriculums(:three).id + fake.sequence = 12 + assert fake.valid? + assert_empty fake.errors[:name] + end + + # validations: numericality + test 'numericality validations for sequence of a curriculum semester' do + @semester.sequence = 0 + assert_not @semester.valid? + assert_not_empty @semester.errors[:sequence] + end + + # custom methods + test 'available_courses method return course for curriculum' do + courses = @semester.available_courses + assert_includes courses, courses(:test) + assert_not_includes courses, courses(:ati) + assert_not_includes courses, Course.passive.first + + courses = @semester.available_courses(add_courses: [courses(:ati)]) + assert_includes courses, courses(:ati) + end +end diff --git a/test/models/course/curriculum_test.rb b/test/models/course/curriculum_test.rb index 92e98bf3d..dbf84218d 100644 --- a/test/models/course/curriculum_test.rb +++ b/test/models/course/curriculum_test.rb @@ -8,18 +8,21 @@ class CurriculumTest < ActiveSupport::TestCase end # relations - test 'curriculum can communicate with unit' do - assert @curriculum.unit - end - - test 'curriculum can communicate with programs' do - assert @curriculum.programs + %i[ + unit + programs + semesters + courses + ].each do |relation| + test "curriculum can communicate with #{relation}" do + assert @curriculum.send(relation) + end end # validations: presence %i[ name - number_of_semesters + semesters_count status unit ].each do |property| @@ -42,10 +45,10 @@ class CurriculumTest < ActiveSupport::TestCase end # validations: numericality - test 'numericality validations for number_of_semesters of a curriculum' do - @curriculum.number_of_semesters = 0 + test 'numericality validations for semesters_count of a curriculum' do + @curriculum.semesters_count = -1 assert_not @curriculum.valid? - assert_not_empty @curriculum.errors[:number_of_semesters] + assert_not_empty @curriculum.errors[:semesters_count] end # enums