Skip to content

Commit

Permalink
L&C / Exams code updates (#1301)
Browse files Browse the repository at this point in the history
* LCPE: added models

* LCPE: added controllers

* LCPE: serializers

* LCPE: mock loading lib

* changes after feedback

* a period

* unperiod

* cosmetic change

* cosmetic

* Fixes for rSpec errors.

* Fixes for RuboCop offenses.

* cosmetic

---------

Co-authored-by: nfstern02 <[email protected]>
  • Loading branch information
binq and nfstern02 authored Feb 4, 2025
1 parent 4ed1ab3 commit b21bdb8
Show file tree
Hide file tree
Showing 30 changed files with 893 additions and 1 deletion.
6 changes: 6 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ Metrics/MethodLength:
- "lib/seed_utils.rb"
- "app/utilities/scorecard_api/service.rb"
- "app/models/converters/accreditation_date_time_converter.rb"
- "app/models/lcpe/**/*.rb"

Metrics/ClassLength:
Exclude:
Expand All @@ -143,6 +144,7 @@ Metrics/ClassLength:
- "app/controllers/v1/institutions_controller.rb"
- "app/serializers/institution_compare_serializer.rb"
- "app/utilities/scorecard_api/service.rb"
- "lib/lcpe/**/*.rb"

Metrics/AbcSize:
Max: 40
Expand Down Expand Up @@ -265,3 +267,7 @@ Layout/SpaceAroundMethodCallOperator:

Style/ExponentialNotation:
Enabled: true

Layout/IndentationConsistency:
Exclude:
- "app/models/lcpe/**/*.rb"
19 changes: 19 additions & 0 deletions app/controllers/v1/lcpe/exams_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# frozen_string_literal: true

class V1::Lcpe::ExamsController < ApiController
def index
results = Lcpe::Exam.with_enriched_id

render json: results, each_serializer: Lcpe::ExamSerializer, adapter: :json, action: 'index'
end

def show
result =
Lcpe::Exam
.by_enriched_id(params[:id])
.includes(%i[tests institution])
.first

render json: result, serializer: Lcpe::ExamSerializer, adapter: :json, action: 'show'
end
end
80 changes: 80 additions & 0 deletions app/controllers/v1/lcpe/lacs_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# frozen_string_literal: true

class V1::Lcpe::LacsController < ApiController
def index
render(
{
json: list,
each_serializer: Lcpe::LacSerializer,
adapter: :json,
action: 'index'
}.tap(&method(:add_pagination_meta))
)
end

def show
result =
Lcpe::Lac
.by_enriched_id(params[:id])
.includes(%i[tests institution])
.first

render json: result, serializer: Lcpe::LacSerializer, adapter: :json, action: 'show'
end

private

def list
return @list if defined?(@list)

@list =
Lcpe::Lac
.with_enriched_id
.where(index_params.permit(:edu_lac_type_nm, :state))
.then do |relation|
relation = relation.where('lac_nm ILIKE ?', "%#{index_params[:lac_nm]}%") if index_params[:lac_nm].present?
relation = relation.paginate(page:, per_page:) if paginate?
relation
end
end

def index_params
return @index_params if defined?(@index_params)

@index_params = params.permit(:edu_lac_type_nm, :state, :lac_nm, :page, :per_page)
end

def page
return @page if defined?(@page)

@page = index_params[:page] || 1
end

def per_page
return @per_page if defined?(@per_page)

@per_page = index_params[:per_page]
end

def paginate_question
return @paginate_question if defined?(@paginate_question)

@paginate_question = index_params[:per_page].present?
end

alias paginate? paginate_question

def add_pagination_meta(signature)
paginate? ? signature.update(meta: pagination_meta) : signature
end

def pagination_meta
{
current_page: list.current_page,
next_page: list.next_page,
prev_page: list.previous_page, # prev_page
total_pages: list.total_pages,
total_count: list.total_entries # total_count
}
end
end
9 changes: 9 additions & 0 deletions app/models/lcpe.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# frozen_string_literal: true

module Lcpe
extend SqlContext

def self.table_name_prefix
'lcpe_'
end
end
65 changes: 65 additions & 0 deletions app/models/lcpe/exam.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# frozen_string_literal: true

module Lcpe
class Exam < ApplicationRecord
REF_CODE_FN = "RIGHT(MD5(CONCAT(facility_code, '-', nexam_nm)), 5)"

extend SqlContext

# using Enriched IDs is a good way to ensure that
# a stale ID preloaded from the browser is not used.
scope :with_enriched_id, lambda {
select(
'*',
"#{REF_CODE_FN} AS ref_code",
"CONCAT(id, '@', #{REF_CODE_FN}) enriched_id"
)
}

scope :by_enriched_id, lambda { |enriched_id|
id, = enriched_id.match(/\A(\d+)@(.+)\z/).values_at(1, 2)

with(enriched_query: with_enriched_id.where('id = ?', id))
.select("#{table_name}.*", 'enriched_query.enriched_id')
.from(table_name.to_s)
.joins("LEFT JOIN enriched_query ON #{table_name}.id = enriched_query.id")
.where('enriched_query.enriched_id = ?', enriched_id)
}

has_many :tests, class_name: 'ExamTest', dependent: :destroy

# rubocop:disable Rails/InverseOf
belongs_to(
:institution,
foreign_key: :facility_code,
primary_key: :facility_code
)
# rubocop:enable Rails/InverseOf

# rubocop:disable Rails/InverseOf
belongs_to(
:weam,
foreign_key: :facility_code,
primary_key: :facility_code
)
# rubocop:enable Rails/InverseOf

def self.rebuild
pure_sql(<<~SQL)
INSERT INTO #{table_name} (id, facility_code, nexam_nm)
SELECT
ROW_NUMBER() OVER () AS id,
facility_code,
nexam_nm
FROM (
SELECT DISTINCT ON (facility_code, nexam_nm)
facility_code,
nexam_nm
FROM lcpe_feed_nexams
) subquery;
CREATE INDEX ON #{table_name} (facility_code);
CREATE INDEX ON #{table_name} (nexam_nm);
SQL
end
end
end
24 changes: 24 additions & 0 deletions app/models/lcpe/exam_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# frozen_string_literal: true

module Lcpe
class ExamTest < ApplicationRecord
extend SqlContext

belongs_to :exam

def self.rebuild
pure_sql(<<~SQL)
INSERT INTO #{table_name} (id, exam_id, descp_txt, fee_amt, begin_dt, end_dt)
SELECT
o.id,
x.id AS exam_id,
o.descp_txt,
o.fee_amt,
o.begin_dt,
o.end_dt
FROM lcpe_feed_nexams o
JOIN lcpe_exams x ON o.facility_code = x.facility_code AND o.nexam_nm = x.nexam_nm;
SQL
end
end
end
12 changes: 12 additions & 0 deletions app/models/lcpe/feed.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# frozen_string_literal: true

module Lcpe::Feed
def self.table_name_prefix
# not going to be pedantic
# parent_pfx = self.module_parent.table_name_prefix
# pfx = "feed_"
# format("%<parent_pfx>s%<pfx>s", {parent_pfx:, pfx:})

'lcpe_feed_'
end
end
23 changes: 23 additions & 0 deletions app/models/lcpe/feed/lac.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# frozen_string_literal: true

module Lcpe
module Feed
class Lac < ImportableRecord
extend SqlContext

CSV_CONVERTER_INFO = {
'facility_code' => { column: :facility_code, converter: Converters::BaseConverter },
'lc_type' => { column: :edu_lac_type_nm, converter: Converters::BaseConverter },
'lc_name' => { column: :lac_nm, converter: Converters::BaseConverter },
'lc_test_name' => { column: :test_nm, converter: Converters::BaseConverter },
'lc_test_fee' => { column: :fee_amt, converter: Converters::BaseConverter }
}.freeze

def self.normalize
pure_sql
.join(Lcpe::Lac.reset)
.join(Lcpe::LacTest.reset)
end
end
end
end
24 changes: 24 additions & 0 deletions app/models/lcpe/feed/nexam.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# frozen_string_literal: true

module Lcpe
module Feed
class Nexam < ImportableRecord
extend SqlContext

CSV_CONVERTER_INFO = {
'facility_code' => { column: :facility_code, converter: Converters::BaseConverter },
'national_exam_name' => { column: :nexam_nm, converter: Converters::BaseConverter },
'nexam_fee_description' => { column: :descp_txt, converter: Converters::BaseConverter },
'nexam_fee_amount' => { column: :fee_amt, converter: Converters::BaseConverter },
'nexam_fee_from_date' => { column: :begin_dt, converter: Converters::BaseConverter },
'nexam_fee_to_date' => { column: :end_dt, converter: Converters::BaseConverter }
}.freeze

def self.normalize
pure_sql
.join(Lcpe::Exam.reset)
.join(Lcpe::ExamTest.reset)
end
end
end
end
74 changes: 74 additions & 0 deletions app/models/lcpe/lac.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# frozen_string_literal: true

module Lcpe
class Lac < ApplicationRecord
REF_CODE_FN = "RIGHT(MD5(CONCAT(facility_code, '-', lac_nm)), 5)"

extend SqlContext

# using Enriched IDs is a good way to ensure that
# a stale ID preloaded from the browser is not used.
scope :with_enriched_id, lambda {
select(
'*',
"#{REF_CODE_FN} AS ref_code",
"CONCAT(id, '@', #{REF_CODE_FN}) enriched_id"
)
}

scope :by_enriched_id, lambda { |enriched_id|
id, = enriched_id.match(/\A(\d+)@(.+)\z/).values_at(1, 2)

with(enriched_query: with_enriched_id.where('id = ?', id))
.select("#{table_name}.*", 'enriched_query.enriched_id')
.from(table_name.to_s)
.joins("LEFT JOIN enriched_query ON #{table_name}.id = enriched_query.id")
.where('enriched_query.enriched_id = ?', enriched_id)
}

has_many :tests, class_name: 'LacTest', dependent: :destroy

# rubocop:disable Rails/InverseOf
belongs_to(
:institution,
foreign_key: :facility_code,
primary_key: :facility_code
)
# rubocop:enable Rails/InverseOf

# rubocop:disable Rails/InverseOf
belongs_to(
:weam,
foreign_key: :facility_code,
primary_key: :facility_code
)
# rubocop:enable Rails/InverseOf

def self.rebuild
pure_sql(<<~SQL)
INSERT INTO #{table_name} (id, facility_code, edu_lac_type_nm, state, lac_nm)
SELECT
ROW_NUMBER() OVER () AS id,
subquery.facility_code,
CASE
WHEN subquery.facility_code LIKE '46P%' THEN 'Prep Course'
ELSE subquery.edu_lac_type_nm
END AS edu_lac_type_nm,
subquery.state,
subquery.lac_nm
FROM (
SELECT DISTINCT ON (facility_code, lac_nm)
feed.facility_code,
feed.edu_lac_type_nm,
i.physical_state as state,
feed.lac_nm
FROM lcpe_feed_lacs feed
JOIN institutions AS i ON i.facility_code = feed.facility_code
) subquery;
CREATE INDEX ON #{table_name} (facility_code);
CREATE INDEX ON #{table_name} (edu_lac_type_nm);
CREATE INDEX ON #{table_name} (lac_nm);
SQL
end
end
end
22 changes: 22 additions & 0 deletions app/models/lcpe/lac_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# frozen_string_literal: true

module Lcpe
class LacTest < ApplicationRecord
extend SqlContext

belongs_to :lac

def self.rebuild
pure_sql(<<~SQL)
INSERT INTO #{table_name} (id, lac_id, test_nm, fee_amt)
SELECT
o.id,
x.id AS lac_id,
o.test_nm,
o.fee_amt
FROM lcpe_feed_lacs o
JOIN lcpe_lacs x ON o.facility_code = x.facility_code AND o.lac_nm = x.lac_nm;
SQL
end
end
end
Loading

0 comments on commit b21bdb8

Please sign in to comment.