kuali_toolbox 0.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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