<commit_before>require './models'
require 'fastercsv'

# Before running this script with a CSV file, prepare it so:
#   - There is only a single line of column headings on the first line of the file
#   - There are no spaces before or after the column headings
#   - The column headings correspond with the key names in the columns{} hash below
#   - The data starts on line 2

def slugify(name)
  output = name.gsub(/[^\w\s-]/, '').gsub(/\s+/, '-').downcase
  output.gsub(/---/, '-')
end

months = %w[ dummy Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec ]

columns = 
  { 
    'Directorate' => nil,
    'Updated'     => nil,
    'Service'     => nil,
    'Supplier'    => nil,
    'Amount'      => nil,
    'Transaction Number' => nil,
   }

directorate_replacements =
  [
  ]

service_replacements = 
  [
  ]
  
count = 0

if ARGV[0].nil?
  puts "Specify the filename of the CSV file to import on the command line"
  exit
end

FasterCSV.foreach(ARGV[0]) do |row|

    count += 1
    
    if (count > 1) # skip first line that doesn't contain data
      
      p row
      
      unless row[columns['Directorate']].nil?
        directorate_name = row[columns['Directorate']].strip.gsub(/&/, "and")
      end
      
      service_name = row[columns['Service']].strip.gsub(/&/, "and")
      supplier_name = row[columns['Supplier']].strip.gsub(/&/, "and")
      
      
      for replacement in directorate_replacements
        if directorate_name == replacement[0]
          directorate_name = replacement[1]
        end
      end
      
      for replacement in service_replacements
        if service_name == replacement[0]
          service_name = replacement[1]
        end
      end
      
      if directorate_name.nil?
        directorate = nil
      else
        directorate = Directorate.first_or_create(:name => directorate_name, :slug => slugify(directorate_name))
        directorate.save
      end
      
      service = Service.first_or_create(:name => service_name, :directorate => directorate, :slug => slugify(service_name))
      service.save
      
      supplier = Supplier.first_or_create(:name => supplier_name, :slug => slugify(supplier_name))
      supplier.save
      
      dt = row[columns['Updated']].strip.split(' ')
      d = Date.new(dt[2].to_i, months.index(dt[1]), dt[0].to_i)

      # Using Payment.new rather than Payment.first_or_new allows us to create genuine duplicates
      # so don't run the importer more than once with the same set of data
      payment = Payment.new(
        'service' =>  service,
        'supplier' => supplier,
        'amount' => row[columns['Amount']].strip.gsub(/,/, ''),
        'd' => d,
        'transaction_id' => row[columns['Transaction Number']].strip.to_i
      )
  
      unless payment.save # save runs callbacks/hooks, save! doesn't
        puts "ERROR: Failed to save payment"
        payment.errors.each do |e|
          puts e
        end
      end
  else
    # Get the column headings
    position = 0

    for column in row
      columns[column] = position
      position += 1
    end
    puts columns.inspect
  end
end<commit_msg>Use CSV class; use ISO8601 dates<commit_after>require './app'
require 'csv'
require 'date'

# Before running this script with a CSV file, prepare it so:
#   - There is only a single line of column headings on the first line of the file
#   - There are no spaces before or after the column headings
#   - The column headings correspond with the key names in the columns{} hash below
#   - The data starts on line 2

def slugify(name)
  output = name.gsub(/[^\w\s-]/, '').gsub(/\s+/, '-').downcase
  output.gsub(/---/, '-')
end

months = %w[ dummy Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec ]

columns = 
  { 
    'Directorate' => nil,
    'Updated'     => nil,
    'Service'     => nil,
    'Supplier'    => nil,
    'Amount'      => nil,
    'Transaction Number' => nil,
   }

directorate_replacements =
  [
  ]

service_replacements = 
  [
  ]
  
count = 0

if ARGV[0].nil?
  puts "Specify the filename of the CSV file to import on the command line"
  exit
end

CSV.foreach(ARGV[0]) do |row|

    count += 1
    
    if (count > 1) # skip first line that doesn't contain data
      
      p row
      
      unless row[columns['Directorate']].nil?
        directorate_name = row[columns['Directorate']].strip.gsub(/&/, "and")
      end
      
      service_name = row[columns['Service']].strip.gsub(/&/, "and")
      supplier_name = row[columns['Supplier']].strip.gsub(/&/, "and")
      
      
      for replacement in directorate_replacements
        if directorate_name == replacement[0]
          directorate_name = replacement[1]
        end
      end
      
      for replacement in service_replacements
        if service_name == replacement[0]
          service_name = replacement[1]
        end
      end
      
      if directorate_name.nil?
        directorate = nil
      else
        directorate = Directorate.first_or_create(:name => directorate_name, :slug => slugify(directorate_name))
        directorate.save
      end
      
      service = Service.first_or_create(:name => service_name, :directorate => directorate, :slug => slugify(service_name))
      service.save
      
      supplier = Supplier.first_or_create(:name => supplier_name, :slug => slugify(supplier_name))
      supplier.save
      
      # dt = row[columns['Updated']].strip.split(' ')
      # d = Date.new(dt[2].to_i, months.index(dt[1]), dt[0].to_i)

      dt = row[columns['Updated']].strip
      if dt =~ /\d{4}-\d{2}-\d{2}/
        d = Date.iso8601(dt)
      end

      # Using Payment.new rather than Payment.first_or_new allows us to create genuine duplicates
      # so don't run the importer more than once with the same set of data
      payment = Payment.new(
        'service' =>  service,
        'supplier' => supplier,
        'amount' => row[columns['Amount']].strip.gsub(/,/, ''),
        'd' => d,
        'transaction_id' => row[columns['Transaction Number']].strip.to_i
      )
  
      unless payment.save # save runs callbacks/hooks, save! doesn't
        puts "ERROR: Failed to save payment"
        payment.errors.each do |e|
          puts e
        end
      end
  else
    # Get the column headings
    position = 0

    for column in row
      columns[column] = position
      position += 1
    end
    puts columns.inspect
  end
end
{'fraction_non_alphanumeric': 0.1170930780097316, 'fraction_numerical': 0.0064354104536179565, 'mean_word_length': 2.341373885684321, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 41, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1627854', 'n_tokens_mistral': 2015, 'n_tokens_neox': 1964, 'n_words': 574}