scottwillson/racing_on_rails

View on GitHub
app/models/results/usac_file.rb

Summary

Maintainability
A
3 hrs
Test Coverage
# frozen_string_literal: true

# compares current members to USAC database for current year
# updates member_usac_to column to 12/31/{year}
module Results
  class USACFile
    attr_accessor :members_list

    USAC_SITE = "www.usacycling.org"
    REGION_FILES = {
      "Central" => "/promoters/wp_p_uscf_ct.csv",
      "Mid-Atlantic" => "/promoters/wp_p_uscf_ma.csv",
      "Mountain" => "/promoters/wp_p_uscf_mt.csv",
      "North Atlantic" => "/promoters/wp_p_uscf_na.csv",
      "North Central" => "/promoters/wp_p_uscf_nc.csv",
      "North West" => "/promoters/wp_p_uscf_nw.csv",
      "South Central" => "/promoters/wp_p_uscf_sc.csv",
      "South East" => "/promoters/wp_p_uscf_se.csv",
      "South West" => "/promoters/wp_p_uscf_sw.csv",
      "West" => "/promoters/wp_p_uscf_we.csv",
      "Wisconsin" => "/promoters/wp_p_uscf_wisc.csv",
      "Complete" => "/promoters/wp_p_uscf_all.csv"
    }.freeze

    def initialize(person = "promo", pword = "races")
      Net::HTTP.start(USAC_SITE) do |http|
        req = Net::HTTP::Get.new(REGION_FILES[RacingAssociation.current.usac_region])
        req.basic_auth person, pword
        response = http.request(req)

        # parses out the data into a 2D array with other properties (such as column referencing like hashes)
        @members_list = if RUBY_VERSION < "1.9"
                          FasterCSV.parse(response.body, col_sep: ",", quote_char: "?", headers: true)
                        else
                          CSV.parse(response.body, col_sep: ",", quote_char: "?", headers: true)
                        end
        clean_headers
      end
    end

    # cleans up the headers so we can make clean column references
    def clean_headers
      @members_list.headers.each do |head|
        head.lstrip!
        head.downcase!
        head.sub!(/ /, "_") # spaces replaced with underscore
      end
    end

    # assumes USAC database contains current year's members only, all licenses good until end of this year
    def update_people
      expir_date = Date.new(Time.zone.today.year, 12, 31)
      people_updated = []
      @members_list.each do |memusac|
        # get the parameters in a nice format
        license = memusac["license#"].to_i.to_s # strips off leading zeros, consistent with our db
        full_name = "#{memusac['first_name']} #{memusac['last_name']}" # as specified by find method used below
        status = memusac["suspension"].to_s

        # Look for the person. License # is most reliable (e.g. we only have short first name)
        # but we may not have their USAC License # yet, so also look by full name
        r = Person.find_by(license: license)
        dups = Person.find_all_by_name_or_alias(first_name: memusac["first_name"], last_name: memusac["last_name"])
        first_dup = dups.first unless dups.first.nil?
        if r.nil?
          r = Person.find_by(name: full_name)
          r ||= first_dup
        elsif r != first_dup
          # we found someone by license.
          begin
            Alias.create!(name: full_name, person: r)
          rescue StandardError
            Rails.logger.warn("Could not create alias #{full_name} for person #{r.name} with license #{r.license}")
          end # the name USAC has does not match Person name or alias
          # Let's make an alias with their name at USAC. Helps with importing results

        end

        unless r.nil? # we found somebody
          if r.license&.match(/\d+/) && r.license != license
            # person has a license, but not this one. we must have the wrong person or other confusion.
            Rails.logger.warn("Had person #{r.name} with license #{r.license} but did not match USAC license #{license} for #{memusac['first_name']} #{memusac['last_name']}")
          else
            # Either the license # matches or we didn't get this data from the member. Either way, safe to overwrite it
            r.license = license
            r.member_usac_to = expir_date
            r.status = status # could be SUSPENDED or PENDING, per USAC IT guys. No current examples
            people_updated.push(r) if r.save!
          end
        end
      end

      Rails.logger.info("#{people_updated.length} people were updated with a USAC expiration date of #{expir_date} ")
      people_updated
    end
  end
end