Skip to content

Commit

Permalink
Merge branch 'main' into assertion-pdf-validation
Browse files Browse the repository at this point in the history
  • Loading branch information
anderson-mj committed Jan 15, 2025
2 parents 75d32f9 + 162753d commit 767e171
Show file tree
Hide file tree
Showing 101 changed files with 4,070 additions and 41 deletions.
3 changes: 2 additions & 1 deletion app/assets/javascripts/form_fields/config_base.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,8 @@ function form_field_config_base(form_field) {
} else if (selected_value == "code") {
form_field.widgets = [
config_form_field_codemirror(form_field, "code", "text/x-ruby"),
config_form_field_condition(form_field, "condition", form_field.condition_options)
config_form_field_condition(form_field, "condition", form_field.condition_options),
config_form_field_select(form_field, "code_type", [["number", "Número"], ["string", "Texto"], ["date", "Data"]], { required: false, default: "number" })
]
} else if (selected_value == "email") {
form_field.widgets = [
Expand Down
2 changes: 1 addition & 1 deletion app/assets/javascripts/form_fields/config_select.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ function config_form_field_select(form_field, field, selectable, options) {
let r = (Math.random() + 1).toString(36).substring(7);
let title = form_field.i18n(field);
let id = `${form_field.baseid}_${field}_${r}`
let value = form_field.data[field] || "";
let value = form_field.data[field] || options["default"] || "";

let options_text = [];
let found = null;
Expand Down
80 changes: 80 additions & 0 deletions app/controllers/assertions_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# Copyright (c) Universidade Federal Fluminense (UFF).
# This file is part of SAPOS. Please, consult the license terms in the LICENSE file.

# frozen_string_literal: true

class AssertionsController < ApplicationController
include SharedPdfConcern

authorize_resource
before_action :permit_query_params

def permit_query_params
params[:query_params].permit! unless params[:query_params].nil?
end

active_scaffold :assertion do |config|
config.action_links.add "simulate",
label: "<i title='#{I18n.t("active_scaffold.assertion.simulate")}' class='fa fa-table'></i>".html_safe,
page: true,
inline: true,
position: :after,
type: :member

form_columns = [
:name, :query, :assertion_template
]

config.create.label = :create_assertion_label
config.list.sorting = { name: "ASC" }
config.list.columns = [:name, :query]
config.columns = form_columns
config.update.columns = form_columns
config.show.columns = form_columns
config.actions.exclude :deleted_records

config.columns[:query].form_ui = :select
end

def simulate
@assertion = Assertion.find(params[:id])
args = @assertion.query.map_params(get_query_params)
result = @assertion.query.execute(args)
@messages = result[:rows] || []
@query_sql = result[:query]

# Allow user to simulate with different arguments
# Analyzes derivations and builds new temporary parameters for missing ones
# Also set simulation_value based on arguments
@query_params = @assertion.query.params

@query_result = result
render action: "simulate"
end

def assertion_pdf
@assertion = Assertion.find(params[:id])
args = @assertion.query.map_params(get_query_params)
@assertion.args = args

respond_to do |format|
format.pdf do
title = I18n.t("pdf_content.assertion.assertion_pdf.filename")
assertion = @assertion.name
filename = "#{title} - #{assertion}.pdf"
send_data render_assertion_pdf(@assertion, filename),
filename: filename,
type: "application/pdf"
end
end
end

private
def get_query_params
return params[:query_params].to_unsafe_h if params[:query_params].is_a?(
ActionController::Parameters
)
params[:query_params] || {}
end

end
12 changes: 12 additions & 0 deletions app/controllers/concerns/shared_pdf_concern.rb
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,16 @@ def render_enrollments_grades_report_pdf(enrollment, filename = "grades_report.p
}
)
end

def render_assertion_pdf(assertion, filename = "assertion.pdf")
render_to_string(
template: "assertions/assertion_pdf",
type: "application/pdf",
formats: [:pdf],
assigns: {
filename: filename,
assertion: assertion
}
)
end
end
2 changes: 1 addition & 1 deletion app/controllers/queries_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class QueriesController < ApplicationController
type: :member

config.update.columns = [:name, :description, :params, :sql]
config.list.columns = [:name, :description, :notifications]
config.list.columns = [:name, :description, :assertions, :notifications]
config.columns[:description].form_ui = :textarea
config.columns[:description].options = { cols: 124, rows: 3 }
config.columns[:params].allow_add_existing = false
Expand Down
6 changes: 3 additions & 3 deletions app/controllers/report_configurations_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class ReportConfigurationsController < ApplicationController
columns = [
:name, :image, :scale, :x, :y, :order, :text, :signature_type,
:preview, :use_at_report, :use_at_transcript,
:use_at_grades_report, :use_at_schedule, :expiration_in_months
:use_at_grades_report, :use_at_schedule, :use_at_assertion, :expiration_in_months
]
config.create.columns = columns
config.update.columns = columns
Expand All @@ -22,7 +22,7 @@ class ReportConfigurationsController < ApplicationController
config.list.columns = [
:name, :order, :text, :signature_type,
:use_at_report, :use_at_transcript, :use_at_grades_report,
:use_at_schedule, :expiration_in_months
:use_at_schedule, :use_at_assertion, :expiration_in_months
]
config.columns[:signature_type].form_ui = :select
config.columns[:signature_type].options = { options: ReportConfiguration.signature_types.keys.map(&:to_sym) }
Expand Down Expand Up @@ -65,7 +65,7 @@ def logo
def record_params
params.required(:record).permit(
:name, :use_at_report, :use_at_transcript, :use_at_grades_report,
:use_at_schedule, :text, :image, :order, :scale,
:use_at_schedule, :use_at_assertion, :text, :image, :order, :scale,
:x, :y, :signature_type, :expiration_in_months
)
end
Expand Down
23 changes: 23 additions & 0 deletions app/helpers/assertions_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# app/helpers/assertions_helper.rb
module AssertionsHelper
include PdfHelper
include AssertionsPdfHelper

def query_sql_form_column(record, options)
code_mirror_view_widget(
"sql_query-view-#{record.id}", "text/x-mysql",
(record.query.try(:sql) || ""), true
)
end

def assertion_template_form_column(record, options)
code_mirror_text_area_widget(
:assertion_template, "record_assertion_template_#{record.id}", "text/html",
options.merge(
value: record.assertion_template ||
I18n.t("active_scaffold.notification.body_template_default")
)
)
end

end
57 changes: 57 additions & 0 deletions app/helpers/assertions_pdf_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# frozen_string_literal: true

# app/helpers/assertions_pdf_helper.rb
module AssertionsPdfHelper
include AssertionHelperConcern

def format_text(bindings, template)
formatter = ErbFormatter.new(bindings)
formatter.format(template)
end

def find_unique_columns(columns, rows)
columns.select do |column|
rows.all? { |row| row[columns.index(column)] == rows.first[columns.index(column)] }
end
end

def assertion_box_text_print(pdf, template, bindings, box_width, box_height)
pdf.move_down 30

text = format_text(bindings, template)

lines = pdf.text_box text, at: [(pdf.bounds.width - box_width) / 2, pdf.cursor], width: box_width, height: box_height, align: :justify, inline_format: true, dry_run: true

while lines.size > 0
not_printed_text_length = lines.map { |line| line[:text].length }.sum
text = text[-not_printed_text_length..-1]

pdf.start_new_page
lines = pdf.text_box text, at: [(pdf.bounds.width - box_width) / 2, pdf.cursor], width: box_width, height: box_height, align: :justify, inline_format: true, dry_run: true
end
end

def assertion_table(pdf, options = {})
assertion = options[:assertion]
args = assertion.args
results = get_query_results(assertion, args)
template = assertion.assertion_template
rows = results[:rows]
columns = results[:columns]

if results[:rows].size == 1
bindings = {}.merge(Hash[columns.zip(rows.first)])
else
unique_columns = find_unique_columns(columns, rows)
bindings = {
rows: rows,
columns: columns
}.merge(Hash[unique_columns.zip(rows.first.values_at(*unique_columns.map { |col| columns.index(col) }))])
end

box_width = 500
box_height = 560

assertion_box_text_print(pdf, template, bindings, box_width, box_height)
end
end
6 changes: 6 additions & 0 deletions app/helpers/concerns/assertion_helper_concern.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# app/helpers/concerns/assertion_helper_concern.rb
module AssertionHelperConcern
def get_query_results(assertion, args)
assertion.query.execute(args)
end
end
24 changes: 16 additions & 8 deletions app/models/ability.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,17 +40,16 @@ class Ability
]

DOCUMENT_MODELS = [
Report
Report, Assertion, Notification, NotificationLog, ReportConfiguration, Query
]

PLACE_MODELS = [
City, State, Country
]

CONFIGURATION_MODELS = [
User, Role, Version, Notification, EmailTemplate, Query, NotificationLog,
CustomVariable, ReportConfiguration,
YearSemester
User, Role, Version, EmailTemplate,
CustomVariable, YearSemester
]

def initialize(user)
Expand Down Expand Up @@ -246,10 +245,21 @@ def initialize_education(user, roles)
end

def initialize_documents(user, roles)
alias_action :execute_now, :execute_now, :notify, to: :update
if roles[:manager]
can :manage, Ability::DOCUMENT_MODELS
cannot :update, Report unless roles[Role::ROLE_ADMINISTRADOR]
end
if roles[Role::ROLE_SECRETARIA]
can :read, [Assertion, Query, NotificationLog]
can :execute, [Assertion, Query]
cannot :read, [ReportConfiguration, Notification]
cannot [:destroy, :update, :create], Query
end
if roles[Role::ROLE_COORDENACAO]
can :manage, (Ability::DOCUMENT_MODELS - [ReportConfiguration])
end
cannot [:destroy, :update, :create], NotificationLog
end

def initialize_places(user, roles)
Expand All @@ -262,15 +272,13 @@ def initialize_configurations(user, roles)
alias_action :execute_now, :execute_now, :notify, to: :update
if roles[Role::ROLE_COORDENACAO]
can :manage, (Ability::CONFIGURATION_MODELS - [
CustomVariable, ReportConfiguration
CustomVariable
])
end
if roles[Role::ROLE_SECRETARIA]
can :read, [Query, Version, NotificationLog]
can :execute, (Query)
can :read, (Version)
end
cannot [:destroy, :update, :create], Role
cannot [:destroy, :update, :create], NotificationLog
cannot [:destroy, :update, :create], Version
end

Expand Down
2 changes: 1 addition & 1 deletion app/models/admissions/admission_committee.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class Admissions::AdmissionCommittee < ActiveRecord::Base
has_many :admission_phases, through: :admission_phase_committees,
class_name: "Admissions::AdmissionPhase"

belongs_to :form_condition, optional:true,
belongs_to :form_condition, optional: true,
class_name: "Admissions::FormCondition"

validates :name, presence: true
Expand Down
1 change: 1 addition & 0 deletions app/models/admissions/admission_phase_evaluation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class Admissions::AdmissionPhaseEvaluation < ActiveRecord::Base
after_initialize :initialize_filled_form

def initialize_filled_form
return if self.admission_phase.blank?
self.filled_form ||= Admissions::FilledForm.new(
is_filled: false,
form_template: self.admission_phase.member_form
Expand Down
2 changes: 2 additions & 0 deletions app/models/admissions/admission_process.rb
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ def max_edit_date
end

def end_greater_than_start_date
return if self.start_date.nil? || self.end_date.nil?
if self.end_date < self.start_date
self.errors.add(:base, :end_greater_than_start_date)
end
Expand All @@ -77,6 +78,7 @@ def max_greater_than_min_letters
end

def simple_url_is_unique_while_open
return if self.end_date.nil?
return if self.end_date < Date.today

if self.simple_url.to_i.to_s == self.simple_url
Expand Down
1 change: 1 addition & 0 deletions app/models/admissions/admission_process_ranking.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class Admissions::AdmissionProcessRanking < ActiveRecord::Base

def that_phase_is_part_of_the_process
return if self.admission_phase.blank?
return if self.admission_process.blank?
self.admission_process.phases.each do |p|
return if p.admission_phase == self.admission_phase
end
Expand Down
1 change: 1 addition & 0 deletions app/models/admissions/admission_ranking_result.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class Admissions::AdmissionRankingResult < ActiveRecord::Base
after_initialize :initialize_filled_form

def initialize_filled_form
return if self.ranking_config.nil?
self.filled_form ||= Admissions::FilledForm.new(
is_filled: false,
form_template: self.ranking_config.form_template
Expand Down
6 changes: 5 additions & 1 deletion app/models/admissions/filled_form_field.rb
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ def validate_file_field(configuration, is_photo: false)
values << ".jpg" if is_photo
filename = self.file.filename.downcase
if values.none? { |ext| filename.end_with?(ext.downcase) }
add_error(:extension, valid: configuration["values"].join(', '))
add_error(:extension, valid: configuration["values"].join(", "))
end
end
end
Expand Down Expand Up @@ -356,6 +356,10 @@ def get_type
else
"string"
end
when Admissions::FormField::CODE
configuration = self.form_field.config_hash
return configuration["code_type"] if configuration["code_type"].present?
"number"
else
"string"
end
Expand Down
1 change: 1 addition & 0 deletions app/models/admissions/letter_request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class Admissions::LetterRequest < ActiveRecord::Base
after_initialize :initialize_filled_form

def initialize_filled_form
return if self.admission_application.blank?
self.filled_form ||= Admissions::FilledForm.new(
is_filled: false,
form_template: self.admission_application.admission_process.letter_template
Expand Down
Loading

0 comments on commit 767e171

Please sign in to comment.