Advertisement
Guest User

Untitled

a guest
Mar 23rd, 2018
132
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Ruby 18.11 KB | None | 0 0
  1. class User < ActiveRecord::Base
  2.   include Publi::UserExtension
  3.   include Report::Reportable
  4.   include ::Rankable
  5.   self.ranking_parent_column_name = :unit_id
  6.   acts_as_paranoid
  7.  
  8.   has_many_roles :admin, :moderator, :evaluative, :academic, :superior, :doctoral, default: :academic
  9.   belongs_to :unit
  10.   has_many :user_units
  11.   has_many :editable_units, through: :user_units, source: :unit
  12.   has_many :surveys
  13.   has_many :achievements
  14.   has_one :job_info
  15.   has_many :achievement_files
  16.  
  17.   devise :database_authenticatable, :timeoutable,
  18.          :rememberable, :trackable, :registerable,
  19.          :validatable, :recoverable
  20.  
  21.   attr_accessor :updated_by, :default_password
  22.   attr_accessible :email, :password, :password_confirmation, :remember_me,
  23.                   :updated_by, :first_name, :last_name, :unit, :unit_id, :all_units,
  24.                   :editable_unit_ids, :job_info_attributes, :default_password, :roles_mask,
  25.                   :deleted_at, :publi_id, :unarchived_at
  26.  
  27.   @@for_select_cache = {}
  28.  
  29.   accepts_nested_attributes_for :job_info
  30.  
  31.   set_mass_actions :destroy, :make_admin, :make_user
  32.   define_perform_action(:make_admin) { role_for_all(:admin) }
  33.   define_perform_action(:make_moderator) { role_for_all(:moderator) }
  34.   define_perform_action(:make_evaluative) { role_for_all(:evaluative) }
  35.   define_perform_action(:make_academic) { role_for_all(:academic) }
  36.   define_perform_action(:make_superior) { role_for_all(:superior) }
  37.   define_perform_action(:make_doctoral) { role_for_all(:doctoral) }
  38.  
  39.   validates :first_name, :last_name, presence: true
  40.   validates :unit_id, presence: true, inclusion: { in: proc { Unit.pluck(:id) } }, reduce: true,
  41.     unless: :admin?
  42.   validates :roles, length: { minimum: 1 }
  43.   validates :publi_id, numericality: true, if: proc { publi_id.present? }
  44.  
  45.   scope :filter_by_created_after, -> (date) { where("`#{table_name}`.`created_at` > ?", Date.parse(date)) }
  46.   scope :filter_by_created_before, -> (date) { where("`#{table_name}`.`created_at` < ?", Date.parse(date)) }
  47.   scope :filter_by_updated_after, -> (date) { where("`#{table_name}`.`updated_at` > ?", Date.parse(date)) }
  48.   scope :filter_by_updated_before, -> (date) { where("`#{table_name}`.`updated_at` < ?", Date.parse(date)) }
  49.   scope :filter_by_archived_after, -> (date) { with_deleted.where("`#{table_name}`.`deleted_at` IS NOT NULL AND `#{table_name}`.`deleted_at` > ?", Date.parse(date)) }
  50.   scope :filter_by_archived_before, -> (date) { with_deleted.where("`#{table_name}`.`deleted_at` IS NOT NULL AND `#{table_name}`.`deleted_at` < ?", Date.parse(date)) }
  51.   scope :filter_by_archived_users, -> (value) { where(value.to_i == 1 ? 'deleted_at IS NOT NULL' : 'deleted_at IS NULL') }
  52.   scope :filter_by_owner, -> (unit_id) { where(unit_id: Unit.find(unit_id).descendants_and_self_ids) }
  53.   scope :filter_by_role, -> (role) { with_role(role) }
  54.   scope :filter_by_match, (lambda do |phrase|
  55.     query = [
  56.       "CONCAT(`#{table_name}`.`first_name`, ' ', `#{table_name}`.`last_name`) LIKE :phrase",
  57.       "`#{table_name}`.`email` LIKE :phrase"
  58.     ]
  59.     where(query.join(' OR '), phrase: "%#{phrase}%")
  60.   end)
  61.  
  62.   scope :with_job_info, -> { joins("LEFT OUTER JOIN `job_infos` ON `#{table_name}`.`id` = `job_infos`.`user_id`") }
  63.  
  64.   scope :with_any_achievement, -> { joins(:achievements).group("`#{table_name}`.`id`").having("COUNT(`achievements`.`id`) > 0") }
  65.   scope :available_for_survey, (lambda do |user|
  66.       with_job_info
  67.       .where("`job_infos`.`job_type` IS NOT NULL AND `job_infos`.`job_type` <> ?", 'nd')
  68.       .where(user.all_units ? {} : { unit_id: user.editable_unit_ids_with_subunits })
  69.     end)
  70.  
  71.   before_validation :clear_units_if_all_units_checked
  72.   after_commit :clear_for_select_cache
  73.  
  74.   def self.for_select(prefix = nil, user = nil)
  75.     @for_select ||= {}
  76.     if user.blank? || user.all_units
  77.       @for_select[prefix] ||= connection.select_all(User.joins(:unit)
  78.       .select('users.id, users.first_name, users.last_name, users.email, units.name as unit_name')
  79.       .order('users.last_name', 'users.first_name')).map do |attributes|
  80.         [user_label(attributes), "#{prefix}#{attributes['id']}"]
  81.       end
  82.     else
  83.       where(unit_id: user.editable_unit_ids_with_subunits).order('last_name, first_name').map do |u|
  84.         [u.label, "#{prefix}#{u.id}"]
  85.       end
  86.     end
  87.   end
  88.  
  89.   def editable_unit_ids_with_subunits
  90.     if self.editable_unit_ids.blank?
  91.       unit.descendants_and_self_ids
  92.     else
  93.       result = []
  94.       self.editable_unit_ids.each do |u|
  95.         result += Unit.find(u).descendants_and_self_ids
  96.       end
  97.       result
  98.     end
  99.   end
  100.  
  101.   def self.unique_api_params
  102.     connection
  103.       .select_all(self.select('first_name, last_name, unit_id, publi_id')
  104.       .order('last_name, first_name, unit_id, publi_id')
  105.       .with_any_role(:academic, :doctoral, :evaluative, :superior))
  106.       .map! { |value| [value['first_name'], value['last_name'], value['unit_id'], value['publi_id']] }
  107.       .uniq
  108.   end
  109.  
  110.   def self.find_by_name(fullname)
  111.     # => hope that all users has names like "Foo Bar" or "Foo Bar-Baz"
  112.     name = fullname.split
  113.     if name.size > 2
  114.       last_name = name.first + ' ' + name.second
  115.       self.where(first_name: name.last, last_name: last_name).first
  116.     else
  117.       self.where(first_name: name.last, last_name: name.first).first
  118.     end
  119.   end
  120.  
  121.   def default_password=(value)
  122.     self.password = self.password_confirmation = @default_password = value
  123.   end
  124.  
  125.   def name
  126.     "#{last_name} #{first_name}"
  127.   end
  128.  
  129.   def label
  130.     "#{name} <#{email}>".tap do |label|
  131.       label << " (#{unit.name})" if unit
  132.     end
  133.   end
  134.  
  135.   def self.user_label(attributes)
  136.     "#{attributes["last_name"]} #{attributes["first_name"]} <#{attributes["email"]}>".tap do |label|
  137.       label << " (#{attributes["unit_name"]})" unless attributes['unit_name'].nil?
  138.     end
  139.   end
  140.  
  141.   # def label
  142.   #   for_select.select do |arr|
  143.   #     arr.last == id.to_s
  144.   #   end.first
  145.   # end
  146.  
  147.   def all_units
  148.     @all_units || editable_units.empty?
  149.   end
  150.  
  151.   def all_units=(value)
  152.     return @all_units = nil if value.nil?
  153.     @all_units = (value.to_i == 1)
  154.   end
  155.  
  156.   def summary(quantitative = false, options = {})
  157.     Fields
  158.     options.delete_if { |_k, v| v.blank? }
  159.  
  160.     archived = !!options[:archived]
  161.     achievements_repository = archived ? achievements.with_deleted.where(archived: archived) : achievements
  162.  
  163.     a = achievements_repository
  164.         .with_points
  165.         .joins(:achievement_type)
  166.         .where(summary_options_to_where_clause(options))
  167.     if quantitative == true
  168.       a.count(:points, group: '`achievement_types`.`group`')
  169.        .tap { |hash| hash.default = 0 }
  170.     else
  171.       a.sum(:points, group: '`achievement_types`.`group`')
  172.        .tap { |hash| hash.default = 0 }
  173.     end
  174.   end
  175.  
  176.   def publications_points
  177.     achievements
  178.       .joins(:achievement_type)
  179.       .where(
  180.         "achievement_types.group = ? AND achievement_types.subgroup IN (?)",
  181.         'II',
  182.         ['1', '2', '3', '4']
  183.         )
  184.       .pluck(:points)
  185.       .sum
  186.   end
  187.  
  188.   def to_xlsx_row
  189.     fields = [
  190.       first_name,
  191.       last_name,
  192.       email,
  193.       unit ? unit.name : 'n/a',
  194.       unit ? unit.parentroot : 'n/a',
  195.       unit ? unit.parentsecond : 'n/a',
  196.       system_roles_str
  197.     ]
  198.     keys = (JobInfo.mile_stones_text + JobInfo.mile_stones_dates)
  199.     if job_info
  200.       keys.each do |key|
  201.         v = job_info.send(key.to_sym)
  202.         fields << (v.blank? ? 'n/a' : v)
  203.       end
  204.     else
  205.       fields += (['n/a'] * keys.size)
  206.     end
  207.  
  208.     fields
  209.   end
  210.  
  211.   def self.to_xlsx
  212.     Axlsx::Package.new do |xls|
  213.       xls.workbook.add_worksheet(name: I18n.t('users.to_xlsx.sheet')) do |sheet|
  214.         sheet << [
  215.           I18n.t('users.to_xlsx.first_name'),
  216.           I18n.t('users.to_xlsx.last_name'),
  217.           I18n.t('users.to_xlsx.email'),
  218.           I18n.t('users.to_xlsx.unit'),
  219.           I18n.t('users.to_xlsx.department'),
  220.           I18n.t('users.to_xlsx.institute'),
  221.           I18n.t('users.to_xlsx.role')
  222.         ] + (JobInfo.mile_stones_text + JobInfo.mile_stones_dates).collect { |key| I18n.t(key, scope: 'users.to_xlsx') }
  223.         scoped.each do |users|
  224.           sheet << users.to_xlsx_row
  225.         end
  226.       end
  227.     end.to_stream.read
  228.   end
  229.  
  230.   def achievement_to_xlsx_row(a, i)
  231.     [
  232.       i,
  233.       a.label,
  234.       a.achievement_year,
  235.       a.points,
  236.       a.created_at.strftime("%F"),
  237.       a.publi_id
  238.     ]
  239.   end
  240.  
  241.   def achievements_to_xlsx(current_user)
  242.     Axlsx::Package.new do |xls|
  243.       xls.workbook.add_worksheet(name: name) do |sheet|
  244.         sheet << ["Wykaz osiągnięć dla pracownika: #{name}"]
  245.         sheet << ["Wygenerowane z systemu BOP #{DateTime.now.strftime("%F")} przez #{current_user.name}"]
  246.  
  247.         sheet << [
  248.           "Lp.",
  249.           "Nazwa osiagnięcia",
  250.           "Rok osiągnięcia",
  251.           "Punkty",
  252.           "Data dodania",
  253.           "Bibliografia ID"
  254.         ]
  255.  
  256.         achievements_repository =
  257.           deleted_at.present? ? achievements.with_deleted.where(archived: true) : achievements
  258.         achievements_repository.each_with_index do |a, i|
  259.           sheet << achievement_to_xlsx_row(a, i + 1)
  260.         end
  261.       end
  262.     end.to_stream.read
  263.   end
  264.  
  265.   def generate_detailed_report(params, created_by_name, archived = false)
  266.     achievements_repository = archived ? achievements.with_deleted.where(archived: true) : achievements
  267.  
  268.     case params[:timespan]
  269.     when 'all'
  270.       @achievements_for_pdf = achievements_repository
  271.       years_params = {}
  272.     when 'year'
  273.       @achievements_for_pdf = achievements_repository.where(achievement_year: params[:year])
  274.       years_params = { year: params[:year] }
  275.     when 'between'
  276.       @achievements_for_pdf = achievements_repository.where('achievement_year >= ? AND achievement_year <= ?', params[:start_year], params[:end_year])
  277.       years_params = { start_year: params[:start_year], end_year: params[:end_year] }
  278.     end
  279.  
  280.     return if @achievements_for_pdf.count.zero?
  281.  
  282.     generate_pdf(created_by_name, years_params)
  283.   end
  284.  
  285.   def system_roles_str
  286.     rstr = ""
  287.     if roles
  288.       roles_str = roles.map { |r| I18n.t("helpers.roles.#{r.to_s}") }
  289.       rstr = roles_str.join(", ")
  290.     end
  291.     return rstr
  292.   end
  293.  
  294.   def is?(*role)
  295.     !(roles & role).empty?
  296.   end
  297.  
  298.   def more_than_one?
  299.     User.where(first_name: first_name, last_name: last_name).size > 1
  300.   end
  301.  
  302.   def user_index
  303.     User.where(first_name: first_name, last_name: last_name).find_index(self) ||
  304.       0
  305.   end
  306.  
  307.   delegate :job_type, :for_survey?, to: :job_info, allow_nil: true
  308.  
  309.   def self.to_autocomplete_json(query = '')
  310.     { suggestions: scoped.select { |u| %r{} === u.label }.map { |user| { value:  user.label, data: { id: user.id, name: user.name } } } }
  311.   end
  312.  
  313.   def managable_units_ids
  314.     units = Unit.where(id: user_units.pluck(:unit_id))
  315.     units.inject([]) { |a, e| e.descendants_and_self_ids }
  316.   end
  317.  
  318.   private
  319.  
  320.   def updated_by_admin?
  321.     updated_by.present? && updated_by.admin?
  322.   end
  323.  
  324.   def password_required?
  325.     super && !updated_by_admin?
  326.   end
  327.  
  328.   def clear_units_if_all_units_checked
  329.     self.editable_units = [] if @all_units == true
  330.   end
  331.  
  332.   def clear_for_select_cache
  333.     @@for_select_cache = {}
  334.     @for_select = {}
  335.   end
  336.  
  337.   # methods for generating detailed report pdf
  338.   def generate_pdf(created_by_name, years_params, output = StringIO.new)
  339.     Prawn::Document.new do |pdf|
  340.       pdf.font 'Open Sans'
  341.       pdf.font_size 10
  342.       pdf.fill_color 'FFFFFF'
  343.  
  344.       @width = [540]
  345.       @column_widths = [30, 60, 340, 60, 50]
  346.       i = 1
  347.       points = { science: 0, dydactic: 0, organization: 0, other: 0 }
  348.  
  349.       by_group = @achievements_for_pdf.group_by do |a|
  350.         a.achievement_type ? a.achievement_type.group_type : :other
  351.       end
  352.  
  353.       by_group.each do |group, as|
  354.         points[group] = as.sum { |a| a.points.to_f }
  355.  
  356.         by_group[group] = as.group_by do |a|
  357.           a.achievement_type ? a.achievement_type.full_group : '0.'
  358.         end
  359.  
  360.         by_group[group].each do |fg, as|
  361.           by_group[group][fg] = as.group_by do |a|
  362.             a.achievement_year
  363.           end
  364.  
  365.           by_group[group][fg] = by_group[group][fg].sort_by { |k, v| k.to_i }.to_h
  366.         end
  367.       end
  368.       by_group.default = {}
  369.  
  370.       generate_header(pdf, created_by_name, years_params)
  371.       pdf.move_down 10
  372.       generate_points_section(pdf, points, by_group[:science])
  373.       pdf.move_down 10
  374.  
  375.       pdf.fill_color '000000'
  376.       pdf.table(
  377.         [['Lp.', 'Grupa', 'Nazwa osiagnięcia', 'Data dodania', 'Punkty']],
  378.         column_widths: @column_widths,
  379.         cell_style: { border_width: 0, padding: [5, 0, 5, 0], font_style: :bold }
  380.       )
  381.  
  382.       groups = [:science, :dydactic, :organization, :other]
  383.       groups.each do |key|
  384.         i = generate_group(pdf, by_group[key], key, i)
  385.       end
  386.  
  387.       pdf.number_pages '<page>', { at: [pdf.bounds.right - 50, 0], align: :right }
  388.     end.render(output)
  389.     output.rewind
  390.     output
  391.   end
  392.  
  393.   def generate_header(pdf, created_by_name, years_params)
  394.     logo_path = Rails.root.join('app', 'assets', 'images', 'logo_us.png')
  395.     pdf.table([[image: logo_path]], cell_style: { border_width: 0 })
  396.     pdf.move_down 10
  397.  
  398.     pdf.table(
  399.       [['Uniwersytet Szczeciński - wykaz osiągnięć naukowych, dydaktycznych, organizacyjnych']],
  400.       column_widths: @width,
  401.       row_colors: ['002060'],
  402.       cell_style: { border_width: 0, padding: [5, 0, 5, 60], font_style: :bold }
  403.     )
  404.  
  405.     pdf.fill_color '000000'
  406.     pdf.table(
  407.       [[last_name + ' ' + first_name]],
  408.       column_widths: @width,
  409.       row_colors: ['D9D9D9'],
  410.       cell_style: { border_width: 0, padding: [5, 0, 5, 3], font_style: :bold }
  411.     )
  412.  
  413.     if unit
  414.       pdf.table(
  415.         [[unit.parentroot]],
  416.         column_widths: @width,
  417.         cell_style: { border_width: 0, padding: [3, 0, 3, 0] }
  418.       )
  419.  
  420.       pdf.table(
  421.         [[unit.name]],
  422.         column_widths: @width,
  423.         cell_style: { border_width: 0, padding: [3, 0, 3, 0], font_style: :bold }
  424.       )
  425.     end
  426.  
  427.     pdf.table(
  428.       [["Wygenerowane z systemu BOP #{Time.current.strftime('%Y-%m-%d')} przez #{created_by_name}"]],
  429.       column_widths: @width,
  430.       cell_style: { border_width: 0, padding: [2, 0, 2, 0], size: 8 }
  431.     )
  432.  
  433.     if years_params[:start_year].present? && years_params[:end_year].present?
  434.       pdf.table(
  435.         [["Zakres lat od #{years_params[:start_year]} do #{years_params[:end_year]}"]],
  436.         column_widths: @width,
  437.         cell_style: { border_width: 0, padding: [2, 0, 2, 0], size: 8 }
  438.       )
  439.     elsif years_params[:year].present?
  440.       pdf.table(
  441.         [["Wybrany rok: #{years_params[:year]}"]],
  442.         column_widths: @width,
  443.         cell_style: { border_width: 0, padding: [2, 0, 2, 0], size: 8 }
  444.       )
  445.     end
  446.   end
  447.  
  448.   def generate_points_section(pdf, points, science_as)
  449.     pdf.fill_color 'FFFFFF'
  450.     pdf.table(
  451.       [['Podsumowanie punktacji:']],
  452.       column_widths: @width,
  453.       row_colors: ['C00000'],
  454.       cell_style: { border_width: 0, font_style: :bold }
  455.     )
  456.  
  457.     table_data = []
  458.     points.each do |group, pts|
  459.       table_data.push(["Suma punktów za #{get_group_title(group).downcase}", pts.round(2)])
  460.     end
  461.  
  462.     pdf.fill_color '000000'
  463.     pdf.table(
  464.       [table_data[0]],
  465.       column_widths: [490, 50],
  466.       row_colors: ['D9D9D9'],
  467.       cell_style: { border_width: 0, font_style: :bold }
  468.     )
  469.  
  470.     science_pts = 0
  471.     science_as.each do |_, years|
  472.       science_pts += years.values.flatten.inject(0) { |sum, a| a.publi_id ? sum + a.points : sum }
  473.     end
  474.     pdf.fill_color '000000'
  475.     pdf.table(
  476.       [['w tym za publikacje', science_pts.round(2)]],
  477.       column_widths: [394, 146],
  478.       row_colors: ['D9D9D9'],
  479.       cell_style: { border_width: 0, font_style: :bold, padding: [0, 0, 0, 102] }
  480.     )
  481.  
  482.     pdf.fill_color '000000'
  483.     pdf.table(
  484.       table_data[1..3],
  485.       column_widths: [490, 50],
  486.       row_colors: ['D9D9D9'],
  487.       cell_style: { border_width: 0, font_style: :bold }
  488.     )
  489.  
  490.     pdf.fill_color 'FFFFFF'
  491.     pdf.table(
  492.       [['Suma punktów za wszystkie osiągnięcia', points.values.sum.round(2)]],
  493.       column_widths: [490, 50],
  494.       row_colors: ['002060'],
  495.       cell_style: { border_width: 0, font_style: :bold }
  496.     )
  497.   end
  498.  
  499.   def generate_group(pdf, full_group, group_name, i)
  500.     pdf.fill_color 'FFFFFF'
  501.     return i if full_group.empty?
  502.  
  503.     pdf.table(
  504.       [[get_group_title(group_name)]],
  505.       column_widths: @width,
  506.       row_colors: ['C00000'],
  507.       cell_style: { border_width: 0, padding: [2, 0, 5, 210], font_style: :bold }
  508.     )
  509.  
  510.     pdf.fill_color '000000'
  511.     full_group.each do |group, years|
  512.       full_group_name =
  513.         if group == '0.'
  514.           'Usunięte grupy osiągnięć'
  515.         else
  516.           AchievementType.find_by_full_group(group).name
  517.         end
  518.       pdf.table(
  519.         [[i, group, full_group_name, '', years.values.flatten.sum { |a| a.points.to_f }.round(2)]],
  520.         column_widths: [30, 60, 400, 0, 50],
  521.         row_colors: ['D9D9D9'],
  522.         cell_style: { border_width: 0, font_style: :bold }
  523.       )
  524.  
  525.       years.each do |year, as|
  526.         pdf.fill_color(year.nil? ? 'FF0000' : 'FFFFFF')
  527.         pdf.table(
  528.           [['', "Rok osiągnięcia: #{year.nil? ? 'BRAK' : year}"]],
  529.           column_widths: [90, 450],
  530.           row_colors: ['002060'],
  531.           cell_style: { border_width: 0, font_style: :bold }
  532.         )
  533.         pdf.fill_color '000000'
  534.  
  535.         as.each do |a|
  536.           pdf.fill_color 'FF0000' if a.points.nil?
  537.           pdf.table(
  538.             [['', '', a.label, a.created_at.strftime('%Y-%m-%d'), a.points.nil? ? 'brak oceny' : a.points.round(2)]],
  539.             column_widths: @column_widths,
  540.             cell_style: { border_width: 0, padding: [5, 0, 5, 5] }
  541.           )
  542.           pdf.fill_color '000000' if a.points.nil?
  543.         end
  544.       end
  545.  
  546.       i += 1
  547.     end
  548.  
  549.     i
  550.   end
  551.  
  552.   def get_group_title(group_name)
  553.     case group_name.to_sym
  554.     when :science then 'Osiągnięcia naukowe'
  555.     when :organization then 'Osiągnięcia organizacyjne'
  556.     when :dydactic then 'Osiągnięcia dydaktyczne'
  557.     else 'Inne osiągnięcia'
  558.     end
  559.   end
  560. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement