kuali_toolbox 0.18

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,57 @@
1
+ # kuali_toolbox
2
+
3
+ [![Build Status](https://travis-ci.org/KualiCo/kuali_toolbox.svg?branch=master)](https://travis-ci.org/KualiCo/kuali_toolbox)
4
+ [![Test Coverage](https://codeclimate.com/github/KualiCo/kuali_toolbox/badges/coverage.svg)](https://codeclimate.com/github/KualiCo/kuali_toolbox)
5
+ [![Gem Version](https://badge.fury.io/rb/kuali_toolbox.svg)](http://badge.fury.io/rb/kuali_toolbox)
6
+
7
+ Client library and command-line tools to help interact with KualiCo's cloud APIs.
8
+
9
+ ## Installation
10
+
11
+ To simply install the gem and provide access to the command line tools:
12
+
13
+ $ gem install kuali_toolbox
14
+
15
+ However, if you would like to reuse the our ruby modules in your own ruby program,
16
+ add this line to your application's Gemfile:
17
+
18
+ ```ruby
19
+ gem 'kuali_toolbox'
20
+ ```
21
+
22
+ And then execute:
23
+
24
+ $ bundle install
25
+
26
+ ## Usage
27
+
28
+ ### transform_CSV_to_HR_XML
29
+
30
+ ```
31
+ Usage: transform_CSV_to_HR_XML [options] csv_file
32
+ -o, --output [xml_file_output] The file in which the the XML data will be writen (defaults to <csv_file>.xml)
33
+ -s [separator_character], The character that separates each column of the CSV file.
34
+ --separator
35
+ -q, --quote [quote_character] The character used to quote fields.
36
+ -e, --email [email_recipients] Email recipient list that will receive job report status.
37
+ -u, --username [username] The username used to authenticate to the HR REST API.
38
+ -p, --password [password] The password used to authenticate to the HR REST API.
39
+ -l, --url [url] The full URL of the HR REST API; e.g. https://localhost/kc-dev/hr-import/hrimport/import
40
+ -h, --help Display this screen
41
+ ```
42
+ > Note: Please be sure to use the [Account_Provisioning_CSV_Template.xlsx](https://github.com/KualiCo/kuali_toolbox/raw/master/Account_Provisioning_CSV_Template.xlsx) template with this tool.
43
+
44
+ ### validate_HR_XML
45
+
46
+ ```
47
+ Usage: validate_HR_XML xml_file
48
+ -h, --help Display this screen
49
+ ```
50
+
51
+ ## Contributing
52
+
53
+ 1. Fork it: https://github.com/KualiCo/kuali_toolbox/fork
54
+ 2. Create your feature branch: `git checkout -b my-new-feature`
55
+ 3. Commit your changes: `git commit -am 'Add some feature'`
56
+ 4. Push to the branch: `git push origin my-new-feature`
57
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,26 @@
1
+ # KualiCo's client library and command-line tool to help interact with KualiCo's cloud APIs.
2
+ # Copyright (C) 2014-2015 KualiCo, Inc.
3
+
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU Affero General Public License as published by
6
+ # the Free Software Foundation, either version 3 of the License, or
7
+ # (at your option) any later version.
8
+
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU Affero General Public License for more details.
13
+
14
+ # You should have received a copy of the GNU Affero General Public License
15
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+
17
+ require "bundler/gem_tasks"
18
+ require "rspec/core/rake_task"
19
+
20
+ task :default => [:spec]
21
+ task :test => [:spec]
22
+
23
+ desc "Run the specs."
24
+ RSpec::Core::RakeTask.new do |t|
25
+ t.pattern = "spec/**/*_spec.rb"
26
+ end
@@ -0,0 +1,332 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'bundler/setup'
5
+
6
+ require 'builder'
7
+ require 'csv'
8
+ require 'optparse'
9
+ require 'rest_client'
10
+ require 'time'
11
+ require 'kuali_toolbox/etl/grm'
12
+
13
+ ETL = KualiCo::ETL
14
+ GRM = KualiCo::ETL::GRM
15
+ TextParseError = KualiCo::ETL::TextParseError
16
+
17
+ def self.parse_command_line_options(
18
+ executable, args, opt={ csv_options: { headers: :first_row,
19
+ header_converters: :symbol,
20
+ skip_blanks: true,
21
+ col_sep: ",", # comma by default
22
+ quote_char: '"', # double quote by default
23
+ }
24
+ } )
25
+ optparse = OptionParser.new do |opts|
26
+ opts.banner = "Usage: #{executable} [options] csv_file"
27
+ opts.on( '-o [xml_file_output]' ,'--output [xml_file_output]', 'The file in which the the XML data will be writen (defaults to <csv_file>.xml)') do |f|
28
+ opt[:xml_filename] = f
29
+ end
30
+ opts.on( '-s [separator_character]' ,'--separator [separator_character]', 'The character that separates each column of the CSV file.' ) do |s|
31
+ opt[:col_sep] = s
32
+ end
33
+ opts.on( '-q [quote_character]' ,'--quote [quote_character]', 'The character used to quote fields.' ) do |q|
34
+ opt[:quote_char] = q
35
+ end
36
+ opts.on( '-e [email_recipients]', '--email [email_recipients]', 'Email recipient list that will receive job report status.' ) do |e|
37
+ opt[:email_recipients] = e
38
+ end
39
+ opts.on( '-u [username]', '--username [username]', 'The username used to authenticate to the HR REST API.' ) do |u|
40
+ opt[:username] = u
41
+ end
42
+ opts.on( '-p [password]', '--password [password]', 'The password used to authenticate to the HR REST API.' ) do |p|
43
+ opt[:password] = p
44
+ end
45
+ opts.on( '-l [url]', '--url [url]', 'The full URL of the HR REST API; e.g. https://localhost/kc-dev/hr-import/hrimport/import' ) do |l|
46
+ opt[:url] = l
47
+ end
48
+ opts.on( '-h', '--help', 'Display this screen' ) do
49
+ puts opts
50
+ exit 1
51
+ end
52
+
53
+ opt[:csv_filename] = args[0] unless opt[:csv_filename]
54
+ if opt[:csv_filename].nil? || opt[:csv_filename].empty?
55
+ puts opts
56
+ exit 1
57
+ end
58
+ end
59
+ optparse.parse!
60
+
61
+ # construct a sensible default ouptput filename
62
+ unless opt[:xml_filename]
63
+ file_extension = File.extname opt[:csv_filename]
64
+ dir_name = File.dirname opt[:csv_filename]
65
+ base_name = File.basename opt[:csv_filename], file_extension
66
+ opt[:xml_filename] = "#{dir_name}/#{base_name}.xml"
67
+ end
68
+
69
+ unless opt[:email_recipients]
70
+ opt[:email_recipients] = "no-reply@kuali.co"
71
+ end
72
+
73
+ if opt[:url]
74
+ unless opt[:username] && opt[:password]
75
+ raise ArgumentError, "Username and password are required when POSTing to a URL!"
76
+ end
77
+ end
78
+
79
+ return opt
80
+ end
81
+
82
+ opt = parse_command_line_options (File.basename $0), ARGF.argv
83
+
84
+ text_parse_errors = []
85
+
86
+ CSV.open(opt[:csv_filename], opt[:csv_options]) do |csv|
87
+ record_count = csv.readlines.count
88
+ csv.rewind # go back to first row
89
+
90
+ File.open(opt[:xml_filename], 'w') do |xml_file|
91
+ xml = Builder::XmlMarkup.new target: xml_file, indent: 2
92
+ xml.instruct! :xml, encoding: "UTF-8"
93
+ xml.hrmanifest "xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance",
94
+ "xsi:schemaLocation" => "https://github.com/KualiCo/ce-tech-docs/tree/master/v1_0 https://raw.github.com/KualiCo/ce-tech-docs/master/v1_0/hrmanifest.xsd",
95
+ xmlns: "https://github.com/KualiCo/ce-tech-docs/tree/master/v1_0",
96
+ schemaVersion: "1.0",
97
+ statusEmailRecipient: opt[:email_recipients],
98
+ reportDate: Time.now.iso8601,
99
+ recordCount: record_count do |hrmanifest|
100
+ hrmanifest.records do |record|
101
+ csv.find_all do |row| # begin processing csv rows
102
+ begin
103
+ xml.record principalId: GRM.parse_principal_id( row[:prncpl_id] ),
104
+ principalName: GRM.parse_principal_name( row[:prncpl_nm] ) do |record|
105
+ record.affiliations do |affiliations|
106
+ aff = {}
107
+ afltn_typ_cd = ETL.parse_string row[:afltn_typ_cd], name: 'AFLTN_TYP_CD', length: 40, required: true
108
+ campus = ETL.parse_string row[:campus_cd], name: 'CAMPUS_CD', length: 2
109
+ aff[:affiliationType] = afltn_typ_cd unless afltn_typ_cd.empty?
110
+ aff[:campus] = campus unless campus.empty?
111
+ aff[:default] = true
112
+ aff[:active] = true
113
+
114
+ affiliations.affiliation aff do |affiliation|
115
+ emp = {}
116
+ emp_stat_cd = GRM.parse_emp_stat_cd row[:emp_stat_cd]
117
+ emp_typ_cd = GRM.parse_emp_typ_cd row[:emp_typ_cd]
118
+ base_slry_amt = ETL.parse_float row[:base_slry_amt], length: 15, name: 'BASE_SLRY_AMT'
119
+ prmry_dept_cd = ETL.parse_string row[:prmry_dept_cd], length: 40, name: 'PRMRY_DEPT_CD'
120
+ emp_id = ETL.parse_string row[:emp_id], length: 40, name: 'EMP_ID'
121
+ emp[:employeeStatus] = emp_stat_cd unless emp_stat_cd.empty?
122
+ emp[:employeeType] = emp_typ_cd unless emp_typ_cd.empty?
123
+ emp[:baseSalaryAmount] = base_slry_amt unless base_slry_amt.nil?
124
+ emp[:primaryDepartment] = prmry_dept_cd unless prmry_dept_cd.empty?
125
+ emp[:employeeId] = emp_id unless emp_id.empty?
126
+ emp[:primaryEmployment] = true
127
+
128
+ affiliation.employment emp
129
+ end
130
+ end # affiliations
131
+
132
+ address = {}
133
+ addr_typ_cd = GRM.parse_address_type_code( row[:addr_typ_cd] )
134
+ addr_line_1 = ETL.parse_string( row[:addr_line_1], name: 'ADDR_LINE_1', length: 45 )
135
+ addr_line_2 = ETL.parse_string( row[:addr_line_2], name: 'ADDR_LINE_2', length: 45 )
136
+ addr_line_3 = ETL.parse_string( row[:addr_line_3], name: 'ADDR_LINE_3', length: 45 )
137
+ city = ETL.parse_string( row[:city], name: 'CITY', length: 30 )
138
+ state_pvc_cd = ETL.parse_string( row[:state_pvc_cd], name: 'STATE_PVC_CD', length: 2 )
139
+ postal_cd = ETL.parse_string( row[:postal_cd], name: 'POSTAL_CD', length: 20 )
140
+ postal_cntry_cd = ETL.parse_string( row[:postal_cntry_cd], name: 'POSTAL_CNTRY_CD', length: 2 )
141
+ address[:addressTypeCode] = addr_typ_cd unless addr_typ_cd.empty?
142
+ address[:addressLine1] = addr_line_1 unless addr_line_1.empty?
143
+ address[:addressLine2] = addr_line_2 unless addr_line_2.empty?
144
+ address[:addressLine3] = addr_line_3 unless addr_line_3.empty?
145
+ address[:city] = city unless city.empty?
146
+ address[:stateOrProvince] = state_pvc_cd unless state_pvc_cd.empty?
147
+ address[:postalCode] = postal_cd unless postal_cd.empty?
148
+ address[:country] = postal_cntry_cd unless postal_cntry_cd.empty?
149
+ unless address.empty?
150
+ record.addresses do |addresses|
151
+ addresses.address address
152
+ end # addresses
153
+ end
154
+
155
+ record.names do |names|
156
+ nm = {}
157
+ nm_typ_cd = GRM.parse_name_code row[:nm_typ_cd]
158
+ prefix_nm = GRM.parse_prefix row[:prefix_nm]
159
+ first_nm = ETL.parse_string row[:first_nm], length: 40, name: 'FIRST_NM'
160
+ middle_nm = ETL.parse_string row[:middle_nm], length: 40, name: 'MIDDLE_NM'
161
+ last_nm = ETL.parse_string row[:last_nm], length: 80, name: 'LAST_NM'
162
+ suffix_nm = GRM.parse_suffix row[:suffix_nm]
163
+ title_nm = ETL.parse_string row[:title_nm], length: 20, name: 'TITLE_NM'
164
+ nm[:nameCode] = nm_typ_cd unless nm_typ_cd.empty?
165
+ nm[:prefix] = prefix_nm unless prefix_nm.empty?
166
+ nm[:firstName] = first_nm unless first_nm.empty?
167
+ nm[:middleName] = middle_nm unless middle_nm.empty?
168
+ nm[:lastName] = last_nm unless last_nm.empty?
169
+ nm[:suffix] = suffix_nm unless suffix_nm.empty?
170
+ nm[:title] = title_nm unless title_nm.empty?
171
+ nm[:default] = true
172
+ nm[:active] = true
173
+
174
+ names.name nm
175
+ end # names
176
+
177
+ ph = {}
178
+ phone_typ_cd = GRM.parse_phone_type row[:phone_typ_cd]
179
+ phone_nbr = GRM.parse_phone_number row[:phone_nbr]
180
+ phone_extn_nbr = ETL.parse_string row[:phone_extn_nbr], length: 8, name: 'PHONE_EXTN_NBR'
181
+ phone_cntry_cd = ETL.parse_string row[:phone_cntry_cd], length: 2, name: 'PHONE_CNTRY_CD'
182
+ ph[:phoneType] = phone_typ_cd unless phone_typ_cd.empty?
183
+ ph[:phoneNumber] = phone_nbr unless phone_nbr.empty?
184
+ ph[:extension] = phone_extn_nbr unless phone_extn_nbr.empty?
185
+ ph[:country] = phone_cntry_cd unless phone_cntry_cd.empty?
186
+ ph[:default] = true
187
+ ph[:active] = true
188
+
189
+ unless phone_typ_cd.empty? || phone_nbr.empty?
190
+ record.phones do |phones|
191
+ phones.phone ph
192
+ end # phones
193
+ end
194
+
195
+ em = {}
196
+ email_typ_cd = GRM.parse_email_type( row[:email_typ_cd] )
197
+ email_addr = GRM.parse_email_address( row[:email_addr] )
198
+ em[:emailType] = email_typ_cd unless email_typ_cd.empty?
199
+ em[:emailAddress] = email_addr unless email_addr.empty?
200
+ em[:default] = true
201
+ em[:active] = true
202
+
203
+ unless email_typ_cd.empty? || email_addr.empty?
204
+ record.emails do |emails|
205
+ emails.email em unless email_addr.empty?
206
+ end # emails
207
+ end
208
+
209
+ ea = {}
210
+ visa_type = ETL.parse_string( row[:visa_type], length: 30, name: 'VISA_TYPE' )
211
+ county = ETL.parse_string( row[:county], length: 30, name: 'COUNTY' )
212
+ age_by_fiscal_year = ETL.parse_integer( row[:age_by_fiscal_year], length: 3, name: 'AGE_BY_FISCAL_YEAR' )
213
+ race = ETL.parse_string( row[:race], length: 30, name: 'RACE' )
214
+ education_level = ETL.parse_string( row[:education_level], length: 30, name: 'EDUCATION_LEVEL' )
215
+ degree = GRM.parse_degree( row[:degree], name: 'DEGREE' )
216
+ major = ETL.parse_string( row[:major], length: 30, name: 'MAJOR' )
217
+ is_handicapped = ETL.parse_boolean( row[:is_handicapped], name: 'IS_HANDICAPPED' )
218
+ handicap_type = ETL.parse_string( row[:handicap_type], length: 30, name: 'HANDICAP_TYPE' )
219
+ is_veteran = ETL.parse_boolean( row[:is_veteran], name: 'IS_VETERAN' )
220
+ veteran_type = ETL.parse_string( row[:veteran_type], length: 30, name: 'VETERAN_TYPE' )
221
+ has_visa = ETL.parse_boolean( row[:has_visa], name: 'HAS_VISA' )
222
+ visa_code = ETL.parse_string( row[:visa_code], length: 20, name: 'VISA_CODE' )
223
+ visa_renewal_date = ETL.parse_string( row[:visa_renewal_date], length: 19, name: 'VISA_RENEWAL_DATE' )
224
+ office_location = ETL.parse_string( row[:office_location], length: 30, name: 'OFFICE_LOCATION' )
225
+ secondry_office_location = ETL.parse_string( row[:secondry_office_location], length: 30, name: 'SECONDRY_OFFICE_LOCATION' )
226
+ school = ETL.parse_string( row[:school], length: 50, name: 'SCHOOL' )
227
+ year_graduated = GRM.parse_year( row[:year_graduated], name: 'YEAR_GRADUATED' )
228
+ directory_department = ETL.parse_string( row[:directory_department], length: 30, name: 'DIRECTORY_DEPARTMENT' )
229
+ directory_title = ETL.parse_string( row[:directory_title], length: 50, name: 'DIRECTORY_TITLE' )
230
+ primary_title = ETL.parse_string( row[:primary_title], length: 51, name: 'PRIMARY_TITLE' )
231
+ vacation_accural = ETL.parse_boolean( row[:vacation_accural], name: 'VACATION_ACCURAL' )
232
+ is_on_sabbatical = ETL.parse_boolean( row[:is_on_sabbatical], name: 'IS_ON_SABBATICAL' )
233
+ id_provided = ETL.parse_string( row[:id_provided], length: 30, name: 'ID_PROVIDED' )
234
+ id_verified = ETL.parse_string( row[:id_verified], length: 30, name: 'ID_VERIFIED' )
235
+ citizenship_type_code = GRM.parse_citizenship_type( row[:citizenship_type_code] )
236
+ multi_campus_principal_id = ETL.parse_string( row[:multi_campus_principal_id], length: 40, name: 'MULTI_CAMPUS_PRINCIPAL_ID' )
237
+ multi_campus_principal_name = ETL.parse_string( row[:multi_campus_principal_name], length: 100, name: 'MULTI_CAMPUS_PRINCIPAL_NAME' )
238
+ salary_anniversary_date = ETL.parse_string( row[:salary_anniversary_date], length: 10, name: 'SALARY_ANNIVERSARY_DATE' )
239
+ ea[:visaType] = visa_type unless visa_type.empty?
240
+ ea[:county] = county unless county.empty?
241
+ ea[:ageByFiscalYear] = age_by_fiscal_year unless age_by_fiscal_year.nil?
242
+ ea[:race] = race unless race.empty?
243
+ ea[:educationLevel] = education_level unless education_level.empty?
244
+ ea[:degree] = degree unless degree.empty?
245
+ ea[:major] = major unless major.empty?
246
+ ea[:handicapped] = is_handicapped unless is_handicapped.nil?
247
+ ea[:handicapType] = handicap_type unless handicap_type.empty?
248
+ ea[:veteran] = is_veteran unless is_veteran.nil?
249
+ ea[:veteranType] = veteran_type unless veteran_type.empty?
250
+ ea[:visa] = has_visa unless has_visa.nil?
251
+ ea[:visaCode] = visa_code unless visa_code.empty?
252
+ ea[:visaRenewalDate] = visa_renewal_date unless visa_renewal_date.empty?
253
+ ea[:officeLocation] = office_location unless office_location.empty?
254
+ ea[:secondaryOfficeLocation] = secondry_office_location unless secondry_office_location.empty?
255
+ ea[:school] = school unless school.empty?
256
+ ea[:yearGraduated] = year_graduated unless year_graduated.empty?
257
+ ea[:directoryDepartment] = directory_department unless directory_department.empty?
258
+ ea[:directoryTitle] = directory_title unless directory_title.empty?
259
+ ea[:primaryTitle] = primary_title unless primary_title.empty?
260
+ ea[:vacationAccrual] = vacation_accural unless vacation_accural.nil?
261
+ ea[:onSabbatical] = is_on_sabbatical unless is_on_sabbatical.nil?
262
+ ea[:idProvided] = id_provided unless id_provided.empty?
263
+ ea[:idVerified] = id_verified unless id_verified.empty?
264
+ ea[:citizenshipType] = citizenship_type_code unless citizenship_type_code.empty?
265
+ ea[:multiCampusPrincipalId] = multi_campus_principal_id unless multi_campus_principal_id.empty?
266
+ ea[:multiCampusPrincipalName] = multi_campus_principal_name unless multi_campus_principal_name.empty?
267
+ ea[:salaryAnniversaryDate] = salary_anniversary_date unless salary_anniversary_date.empty?
268
+
269
+ record.kcExtendedAttributes ea
270
+
271
+ ap = {}
272
+ unit_number = ETL.parse_string( row[:unit_number], length: 8, name: 'UNIT_NUMBER' )
273
+ appointment_type_code = ETL.parse_string( row[:appointment_type_code], length: 3, name: 'APPOINTMENT_TYPE_CODE' )
274
+ job_code = ETL.parse_string( row[:job_code], length: 6, name: 'JOB_CODE' )
275
+ salary = ETL.parse_float( row[:salary], length: 15, name: 'SALARY' )
276
+ appointment_start_date = ETL.parse_string( row[:appointment_start_date], name: 'APPOINTMENT_START_DATE' )
277
+ appointment_end_date = ETL.parse_string( row[:appointment_end_date], name: 'APPOINTMENT_END_DATE' )
278
+ job_title = ETL.parse_string( row[:job_title], length: 50, name: 'JOB_TITLE' )
279
+ prefered_job_title = ETL.parse_string( row[:prefered_job_title], length: 51, name: 'PREFERED_JOB_TITLE' )
280
+ ap[:unitNumber] = unit_number unless unit_number.empty?
281
+ ap[:appointmentType] = appointment_type_code unless appointment_type_code.empty?
282
+ ap[:jobCode] = job_code unless job_code.empty?
283
+ ap[:salary] = salary unless salary.nil?
284
+ ap[:startDate] = appointment_start_date unless appointment_start_date.empty?
285
+ ap[:endDate] = appointment_end_date unless appointment_end_date.empty?
286
+ ap[:jobTitle] = job_title unless job_title.empty?
287
+ ap[:preferedJobTitle] = prefered_job_title unless prefered_job_title.empty?
288
+
289
+ unless unit_number.empty? || job_code.empty?
290
+ record.appointments do |appointments|
291
+ appointments.appointment ap
292
+ end # appointments
293
+ end
294
+ end # record
295
+
296
+ rescue TextParseError => e
297
+ puts e.message
298
+ text_parse_errors.push e
299
+ end
300
+ end # row
301
+ end # record
302
+ end # hrmanifest
303
+ end # xml_file
304
+ end # csv
305
+
306
+ def number_of_errors(parse_errors_array)
307
+ num_errors = 0
308
+ unless parse_errors_array.empty?
309
+ parse_errors_array.each do |err|
310
+ num_errors += 1 if err.message.start_with? "ERROR"
311
+ end
312
+ end
313
+ return num_errors
314
+ end
315
+
316
+ num_errors = number_of_errors text_parse_errors
317
+ if num_errors > 0
318
+ puts "\n#{num_errors} errors found and must be corrected.\n\n"
319
+ File.unlink opt[:xml_filename]
320
+ exit 1
321
+ end
322
+
323
+ puts "\nXML file written to #{opt[:xml_filename]}\n\n"
324
+
325
+ exit 1 unless GRM.validate_hr_xml opt[:xml_filename]
326
+
327
+ # POST the XML file to the server if opt[:url]
328
+ if opt[:url]
329
+ resource = RestClient::Resource.new( opt[:url], opt[:username], opt[:password] )
330
+ resource.post file: File.new(opt[:xml_filename], 'rt'), content_type: 'multipart/form-data', multipart: true
331
+ puts "\n"
332
+ end
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'bundler/setup'
5
+
6
+ require 'optparse'
7
+ require 'kuali_toolbox/etl/grm'
8
+
9
+ GRM = KualiCo::ETL::GRM
10
+
11
+ def self.parse_command_line_options( executable, args, opt={} )
12
+ optparse = OptionParser.new do |opts|
13
+ opts.banner = "Usage: #{executable} xml_file"
14
+ opts.on( '-h', '--help', 'Display this screen' ) do
15
+ puts opts
16
+ exit 1
17
+ end
18
+
19
+ opt[:xml_filename] = args[0] unless opt[:xml_filename]
20
+ if opt[:xml_filename].nil? || opt[:xml_filename].empty?
21
+ puts opts
22
+ exit 1
23
+ end
24
+ end
25
+ optparse.parse!
26
+
27
+ return opt
28
+ end
29
+
30
+ opt = parse_command_line_options (File.basename $0), ARGF.argv
31
+
32
+ exit 1 unless GRM.validate_hr_xml opt[:xml_filename]
@@ -0,0 +1,48 @@
1
+ # KualiCo's client library and command-line tool to help interact with KualiCo's cloud APIs.
2
+ # Copyright (C) 2014-2015 KualiCo, Inc.
3
+
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU Affero General Public License as published by
6
+ # the Free Software Foundation, either version 3 of the License, or
7
+ # (at your option) any later version.
8
+
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU Affero General Public License for more details.
13
+
14
+ # You should have received a copy of the GNU Affero General Public License
15
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+
17
+ # coding: utf-8
18
+ lib = File.expand_path('../lib', __FILE__)
19
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
20
+ require 'kuali_toolbox/version'
21
+
22
+ Gem::Specification.new do |spec|
23
+ spec.name = "kuali_toolbox"
24
+ spec.version = KualiCo::VERSION
25
+ spec.authors = ["Lance Speelmon"]
26
+ spec.email = ["lspeelmon@kuali.co"]
27
+ spec.summary = %q{Client library and command-line tools to help interact with KualiCo's cloud APIs.}
28
+ # spec.description = %q{TODO: Write a longer description. Optional.}
29
+ spec.homepage = "http://kualico.github.io/kuali_toolbox/"
30
+ spec.metadata = { "issue_tracker" => "https://github.com/KualiCo/kuali_toolbox/issues" }
31
+ spec.license = "AGPL-3.0"
32
+
33
+ spec.files = `git ls-files -z`.split("\x0")
34
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
35
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
36
+ spec.require_paths = ["lib"]
37
+
38
+ spec.add_runtime_dependency 'builder', '~> 3.2.2'
39
+ spec.add_runtime_dependency 'nokogiri', '~> 1.6.3.1'
40
+ spec.add_runtime_dependency 'rest-client', '~> 1.7.2'
41
+
42
+ spec.required_ruby_version = '>= 1.9'
43
+ spec.add_development_dependency "bundler", "~> 1.6"
44
+ spec.add_development_dependency "rake", "~> 10.0"
45
+ spec.add_development_dependency "rspec", "~> 3.0.0"
46
+ # spec.add_development_dependency "simplecov"
47
+ spec.add_development_dependency "codeclimate-test-reporter"
48
+ end