tyler_efm_client 1.0.0.pre.alpha.1

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.
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TylerEfmClient
4
+ ##
5
+ # Result from authentication request
6
+ class AuthenticationResult
7
+ attr_reader :success, :password_hash, :user_id, :first_name, :last_name,
8
+ :email, :expiration_date, :error_code, :error_message
9
+
10
+ def initialize(success: false, password_hash: nil, user_id: nil, first_name: nil,
11
+ last_name: nil, email: nil, expiration_date: nil, error_code: nil, error_message: nil)
12
+ @success = success
13
+ @password_hash = password_hash
14
+ @user_id = user_id
15
+ @first_name = first_name
16
+ @last_name = last_name
17
+ @email = email
18
+ @expiration_date = expiration_date
19
+ @error_code = error_code
20
+ @error_message = error_message
21
+ end
22
+
23
+ ##
24
+ # Returns true if authentication was successful
25
+ def success?
26
+ @success
27
+ end
28
+
29
+ ##
30
+ # Returns a hash representation of the result
31
+ def to_h
32
+ {
33
+ success: @success,
34
+ password_hash: @password_hash,
35
+ user_id: @user_id,
36
+ first_name: @first_name,
37
+ last_name: @last_name,
38
+ email: @email,
39
+ expiration_date: @expiration_date,
40
+ error_code: @error_code,
41
+ error_message: @error_message
42
+ }
43
+ end
44
+ end
45
+
46
+ ##
47
+ # Response from EFM service call
48
+ class ServiceResponse
49
+ attr_reader :success, :status_code, :raw_xml, :json_data, :error_message
50
+
51
+ def initialize(success: false, status_code: 0, raw_xml: '', json_data: nil, error_message: nil)
52
+ @success = success
53
+ @status_code = status_code
54
+ @raw_xml = raw_xml
55
+ @json_data = json_data
56
+ @error_message = error_message
57
+ end
58
+
59
+ ##
60
+ # Returns true if the service call was successful
61
+ def success?
62
+ @success
63
+ end
64
+
65
+ ##
66
+ # Returns a hash representation of the response
67
+ def to_h
68
+ {
69
+ success: @success,
70
+ status_code: @status_code,
71
+ raw_xml: @raw_xml,
72
+ json_data: @json_data,
73
+ error_message: @error_message
74
+ }
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TylerEfmClient
4
+ # Current version of the Tyler EFM Client gem
5
+ VERSION = '1.0.0.pre.alpha.1'
6
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'tyler_efm_client/version'
4
+ require_relative 'tyler_efm_client/client'
5
+ require_relative 'tyler_efm_client/errors'
6
+ require_relative 'tyler_efm_client/result_types'
7
+
8
+ ##
9
+ # Tyler EFM Client - Ruby SDK for Tyler Technologies Electronic Filing Manager (EFM) Services
10
+ #
11
+ # This gem provides a simple, production-ready interface for integrating with Tyler's
12
+ # ECF (Electronic Court Filing) services, including authentication and SOAP service calls.
13
+ #
14
+ # Author:: Tyler Technologies ECF Integration Team
15
+ # License:: MIT
16
+ #
17
+ # @example Basic usage
18
+ # client = TylerEfmClient::Client.new
19
+ #
20
+ # # Authenticate
21
+ # auth_result = client.authenticate(
22
+ # base_url: "https://server.com/EFM/EFMUserService.svc",
23
+ # pfx_file: "certificate.pfx",
24
+ # pfx_password: "password",
25
+ # user_email: "user@example.com",
26
+ # user_password: "userpass"
27
+ # )
28
+ #
29
+ # if auth_result.success?
30
+ # # Call a service
31
+ # response = client.call_service(
32
+ # base_url: "https://server.com/efm/v5/CourtRecordService.svc",
33
+ # password_hash: auth_result.password_hash,
34
+ # operation: "GetCaseList",
35
+ # soap_body: "<GetCaseListRequest>...</GetCaseListRequest>",
36
+ # user_email: "user@example.com",
37
+ # return_json: true
38
+ # )
39
+ # end
40
+ module TylerEfmClient
41
+ end
data/publish_gem.rb ADDED
@@ -0,0 +1,155 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'fileutils'
5
+
6
+ ##
7
+ # Publication script for Tyler EFM Client Ruby gem
8
+ def run_command(command, description)
9
+ puts "🔄 #{description}..."
10
+ result = system(command)
11
+ if result
12
+ puts "✅ #{description} completed"
13
+ true
14
+ else
15
+ puts "❌ #{description} failed"
16
+ false
17
+ end
18
+ end
19
+
20
+ def clean_build
21
+ puts '🧹 Cleaning previous build artifacts...'
22
+
23
+ files_to_clean = ['*.gem', 'Gemfile.lock']
24
+ files_to_clean.each do |pattern|
25
+ Dir.glob(pattern).each do |file|
26
+ File.delete(file)
27
+ puts " Removed: #{file}"
28
+ end
29
+ end
30
+
31
+ puts '✅ Build artifacts cleaned'
32
+ end
33
+
34
+ def pre_publication_checks
35
+ puts '🔍 Running pre-publication checks...'
36
+
37
+ # Check for required files
38
+ required_files = ['lib/tyler_efm_client.rb', 'README.md', 'LICENSE', 'CHANGELOG.md']
39
+ missing_files = required_files.reject { |file| File.exist?(file) }
40
+
41
+ unless missing_files.empty?
42
+ puts "❌ Missing required files: #{missing_files.join(', ')}"
43
+ return false
44
+ end
45
+
46
+ # Check version in gemspec
47
+ unless File.read('tyler_efm_client.gemspec').include?('1.0.0')
48
+ puts '❌ Version not found in gemspec'
49
+ return false
50
+ end
51
+
52
+ puts '✅ Pre-publication checks passed'
53
+ true
54
+ end
55
+
56
+ def build_and_verify_gem
57
+ puts '🔨 Building gem...'
58
+
59
+ unless run_command('gem build tyler_efm_client.gemspec', 'Building gem')
60
+ return false
61
+ end
62
+
63
+ # Verify the built gem
64
+ gem_file = 'tyler_efm_client-1.0.0.gem'
65
+ unless File.exist?(gem_file)
66
+ puts "❌ Gem file #{gem_file} not found after build"
67
+ return false
68
+ end
69
+
70
+ size = File.size(gem_file)
71
+ puts "📦 Built gem: #{gem_file} (#{size} bytes)"
72
+
73
+ # Verify gem contents
74
+ puts '🔍 Verifying gem contents...'
75
+ result = `gem specification #{gem_file} 2>&1`
76
+ if $?.success?
77
+ puts '✅ Gem structure verified'
78
+ true
79
+ else
80
+ puts "❌ Gem verification failed: #{result}"
81
+ false
82
+ end
83
+ end
84
+
85
+ def publish_gem
86
+ gem_file = 'tyler_efm_client-1.0.0.gem'
87
+
88
+ puts '🚀 Publishing gem to RubyGems.org...'
89
+ puts "📋 About to publish: #{gem_file}"
90
+ puts
91
+ puts '⚠️ IMPORTANT: Make sure you have:'
92
+ puts ' 1. Created your RubyGems.org account'
93
+ puts ' 2. Verified your email address'
94
+ puts ' 3. Set up API key with: gem signin'
95
+ puts
96
+ print 'Continue with publication? (y/N): '
97
+
98
+ response = STDIN.gets.chomp.downcase
99
+ unless response == 'y' || response == 'yes'
100
+ puts '📦 Publication cancelled. Gem is ready when you are!'
101
+ return true
102
+ end
103
+
104
+ if run_command("gem push #{gem_file}", 'Publishing to RubyGems.org')
105
+ puts
106
+ puts '🎉 Gem published successfully!'
107
+ puts "📋 Your gem is now available at: https://rubygems.org/gems/tyler_efm_client"
108
+ puts
109
+ puts '📚 Next steps:'
110
+ puts ' 1. Verify the gem page on RubyGems.org'
111
+ puts ' 2. Test installation: gem install tyler_efm_client'
112
+ puts ' 3. Update any documentation with the new gem location'
113
+ true
114
+ else
115
+ puts '❌ Publication failed. Please check your RubyGems.org credentials and try again.'
116
+ false
117
+ end
118
+ end
119
+
120
+ def main
121
+ puts 'Tyler EFM Client - Ruby Gem Publication Script'
122
+ puts '=' * 55
123
+
124
+ # Clean previous builds
125
+ clean_build
126
+
127
+ # Run pre-publication checks
128
+ unless pre_publication_checks
129
+ puts '❌ Pre-publication checks failed. Please fix issues and try again.'
130
+ return false
131
+ end
132
+
133
+ # Install dependencies
134
+ unless run_command('bundle install', 'Installing dependencies')
135
+ return false
136
+ end
137
+
138
+ # Build and verify gem
139
+ unless build_and_verify_gem
140
+ puts '❌ Gem build or verification failed.'
141
+ return false
142
+ end
143
+
144
+ # Run tests one more time
145
+ puts '🧪 Running final tests...'
146
+ unless run_command('ruby test_gem.rb', 'Running gem tests')
147
+ puts '❌ Tests failed. Please fix issues before publishing.'
148
+ return false
149
+ end
150
+
151
+ # Publish gem
152
+ publish_gem
153
+ end
154
+
155
+ exit(main ? 0 : 1) if __FILE__ == $0
@@ -0,0 +1,332 @@
1
+ # Court Filing Workflow Samples - Ruby
2
+
3
+ This directory contains complete examples for common court filing workflows using the Tyler EFM Ruby SDK.
4
+
5
+ ## 📋 Overview
6
+
7
+ These samples demonstrate real-world integration patterns for:
8
+ - Document filing processes
9
+ - Case status checking
10
+ - Filing status monitoring
11
+ - Error handling and retry logic
12
+
13
+ ## 🗂️ Samples Included
14
+
15
+ ### 1. Basic Document Filing (`file_document.rb`)
16
+ Complete workflow for filing a document:
17
+ - Authenticate with Tyler EFM
18
+ - Prepare filing metadata
19
+ - Submit document for filing
20
+ - Monitor filing status
21
+
22
+ ### 2. Filing Status Check (`check_filing_status.rb`)
23
+ Monitor the status of filed documents:
24
+ - Check filing progress
25
+ - Handle different status types
26
+ - Implement polling logic
27
+ - Process completion notifications
28
+
29
+ ### 3. Multi-Document Filing (`bulk_filing.rb`)
30
+ File multiple documents in a single workflow:
31
+ - Batch document preparation
32
+ - Sequential filing process
33
+ - Error handling for partial failures
34
+ - Summary reporting
35
+
36
+ ## 🚀 Quick Start
37
+
38
+ ### Prerequisites
39
+ ```bash
40
+ gem install tyler_efm_client
41
+ ```
42
+
43
+ ### Configuration
44
+ Create a `config.json` file:
45
+ ```json
46
+ {
47
+ "staging": {
48
+ "user_service": "https://georgia-stage.tylertech.cloud/EFM/EFMUserService.svc",
49
+ "court_service": "https://georgia-stage.tylertech.cloud/efm/v5/CourtRecordService.svc",
50
+ "cert_file": "path/to/certificate.pfx",
51
+ "cert_password": "certificate_password",
52
+ "user_email": "your-email@example.com",
53
+ "user_password": "your_password"
54
+ }
55
+ }
56
+ ```
57
+
58
+ ### Run Samples
59
+ ```bash
60
+ ruby file_document.rb
61
+ ruby check_filing_status.rb
62
+ ruby bulk_filing.rb
63
+ ```
64
+
65
+ ## 📖 Sample Details
66
+
67
+ ### File Document Workflow
68
+
69
+ ```ruby
70
+ require 'tyler_efm_client'
71
+
72
+ class DocumentFilingWorkflow
73
+ def initialize(config)
74
+ @config = config
75
+ @client = TylerEfmClient::Client.new
76
+ @password_hash = nil
77
+ end
78
+
79
+ def file_document_workflow(case_id:, document_path:, document_type: 'Motion')
80
+ # Step 1: Authenticate
81
+ authenticate_user
82
+
83
+ # Step 2: Prepare filing
84
+ filing_data = prepare_filing_request(
85
+ case_id: case_id,
86
+ doc_type: document_type,
87
+ document_path: document_path
88
+ )
89
+
90
+ # Step 3: Submit filing
91
+ filing_result = submit_filing(filing_data)
92
+
93
+ # Step 4: Monitor status
94
+ if filing_result[:success]
95
+ final_status = monitor_filing_status(filing_result[:filing_id])
96
+ return final_status
97
+ end
98
+
99
+ filing_result
100
+ end
101
+ end
102
+ ```
103
+
104
+ ### Status Monitoring with Ruby Blocks
105
+
106
+ ```ruby
107
+ def monitor_filing_status(filing_id, timeout_minutes: 30)
108
+ start_time = Time.now
109
+ timeout_seconds = timeout_minutes * 60
110
+
111
+ loop do
112
+ elapsed = Time.now - start_time
113
+ break if elapsed > timeout_seconds
114
+
115
+ status_response = check_filing_status(filing_id)
116
+
117
+ case status_response[:status]
118
+ when 'Complete', 'Filed'
119
+ return status_response
120
+ when 'Error', 'Rejected'
121
+ return status_response
122
+ else
123
+ puts "Status: #{status_response[:status]} - Waiting..."
124
+ sleep(30)
125
+ end
126
+ end
127
+
128
+ raise StandardError, "Filing status check timed out after #{timeout_minutes} minutes"
129
+ end
130
+ ```
131
+
132
+ ## 🔧 Ruby-Specific Patterns
133
+
134
+ ### 1. Hash-Based Configuration
135
+ ```ruby
136
+ class FilingConfiguration
137
+ attr_reader :environment, :config
138
+
139
+ def initialize(config_file: 'config.json', environment: :staging)
140
+ @environment = environment
141
+ @config = load_config(config_file)
142
+ end
143
+
144
+ private
145
+
146
+ def load_config(config_file)
147
+ raise "Configuration file not found: #{config_file}" unless File.exist?(config_file)
148
+
149
+ require 'json'
150
+ config = JSON.parse(File.read(config_file), symbolize_names: true)
151
+
152
+ raise "Environment '#{environment}' not found in config" unless config[environment]
153
+
154
+ config[environment]
155
+ end
156
+ end
157
+ ```
158
+
159
+ ### 2. Method Chaining
160
+ ```ruby
161
+ class TylerEfmWorkflow
162
+ def initialize
163
+ @client = TylerEfmClient::Client.new
164
+ end
165
+
166
+ def authenticate(config)
167
+ @auth_result = @client.authenticate(**config)
168
+ raise TylerEfmClient::AuthenticationError, @auth_result.error_message unless @auth_result.success?
169
+ self
170
+ end
171
+
172
+ def file_document(case_id:, document_path:, **options)
173
+ # Implementation
174
+ self
175
+ end
176
+
177
+ def monitor_status(filing_id, **options)
178
+ # Implementation
179
+ self
180
+ end
181
+ end
182
+
183
+ # Usage
184
+ workflow = TylerEfmWorkflow.new
185
+ .authenticate(config)
186
+ .file_document(case_id: '12345', document_path: 'motion.pdf')
187
+ .monitor_status(filing_id, timeout_minutes: 30)
188
+ ```
189
+
190
+ ### 3. Error Handling with Custom Exceptions
191
+ ```ruby
192
+ module TylerEfmWorkflow
193
+ class FilingError < StandardError
194
+ attr_reader :filing_id, :error_code
195
+
196
+ def initialize(message, filing_id: nil, error_code: nil)
197
+ super(message)
198
+ @filing_id = filing_id
199
+ @error_code = error_code
200
+ end
201
+ end
202
+
203
+ def robust_filing_workflow
204
+ yield
205
+ rescue TylerEfmClient::AuthenticationError => e
206
+ puts "Authentication failed: #{e.message}"
207
+ # Handle authentication issues
208
+ rescue TylerEfmClient::ServiceError => e
209
+ puts "Service error: #{e.message}"
210
+ # Handle service-specific errors
211
+ rescue FilingError => e
212
+ puts "Filing error: #{e.message}"
213
+ puts "Filing ID: #{e.filing_id}" if e.filing_id
214
+ puts "Error Code: #{e.error_code}" if e.error_code
215
+ rescue StandardError => e
216
+ puts "Unexpected error: #{e.message}"
217
+ # Handle unexpected issues
218
+ end
219
+ end
220
+ ```
221
+
222
+ ### 4. Document Preparation with Ruby
223
+ ```ruby
224
+ require 'base64'
225
+ require 'pathname'
226
+
227
+ def prepare_document_for_filing(document_path, document_type: 'Motion')
228
+ doc_path = Pathname.new(document_path)
229
+ raise "Document not found: #{document_path}" unless doc_path.exist?
230
+
231
+ # Read and encode document
232
+ document_content = doc_path.binread
233
+ encoded_content = Base64.strict_encode64(document_content)
234
+
235
+ {
236
+ filename: doc_path.basename.to_s,
237
+ content: encoded_content,
238
+ content_type: 'application/pdf',
239
+ document_type: document_type,
240
+ size: document_content.bytesize
241
+ }
242
+ end
243
+ ```
244
+
245
+ ## 📊 Ruby Response Handling
246
+
247
+ ### Using Structs for Response Objects
248
+ ```ruby
249
+ FilingResponse = Struct.new(:success, :filing_id, :status, :message, :errors, keyword_init: true) do
250
+ def accepted?
251
+ %w[Accepted Processing].include?(status)
252
+ end
253
+
254
+ def complete?
255
+ %w[Complete Filed].include?(status)
256
+ end
257
+
258
+ def error?
259
+ %w[Error Rejected].include?(status) || !errors.empty?
260
+ end
261
+ end
262
+ ```
263
+
264
+ ### Pattern Matching (Ruby 3.0+)
265
+ ```ruby
266
+ def handle_filing_response(response)
267
+ case response
268
+ in { success: true, status: 'Complete' | 'Filed' }
269
+ puts "✅ Filing completed successfully"
270
+ in { success: true, status: 'Processing' | 'Accepted' }
271
+ puts "⏳ Filing is being processed"
272
+ in { success: false, error_message: message }
273
+ puts "❌ Filing failed: #{message}"
274
+ else
275
+ puts "⚠️ Unknown response format"
276
+ end
277
+ end
278
+ ```
279
+
280
+ ## 🔍 Troubleshooting Ruby-Specific Issues
281
+
282
+ ### Gem Installation Issues
283
+ ```ruby
284
+ # Check Ruby version
285
+ puts RUBY_VERSION # Should be 2.7+
286
+
287
+ # Check installed gems
288
+ puts Gem.loaded_specs['tyler_efm_client']&.version
289
+
290
+ # Verify dependencies
291
+ require 'nokogiri'
292
+ puts Nokogiri::VERSION
293
+ ```
294
+
295
+ ### Encoding Issues
296
+ ```ruby
297
+ # Ensure proper encoding for file operations
298
+ File.open(document_path, 'rb:BINARY') do |file|
299
+ content = file.read
300
+ Base64.strict_encode64(content)
301
+ end
302
+ ```
303
+
304
+ ### SSL Certificate Issues
305
+ ```ruby
306
+ # Debug SSL issues
307
+ require 'openssl'
308
+ puts OpenSSL::OPENSSL_VERSION
309
+
310
+ # Check certificate
311
+ cert = OpenSSL::PKCS12.new(File.binread(pfx_file), password)
312
+ puts "Certificate subject: #{cert.certificate.subject}"
313
+ ```
314
+
315
+ ## 🔗 Related Documentation
316
+
317
+ - [Getting Started Guide](../../docs/getting_started.md)
318
+ - [Authentication Guide](../../docs/authentication_guide.md)
319
+ - [API Reference](../../docs/api_reference.md)
320
+ - [Case Management Samples](../case_management/)
321
+
322
+ ## 📞 Support
323
+
324
+ For Ruby-specific filing workflow questions:
325
+ 1. Review Tyler ECF documentation
326
+ 2. Check Ruby version compatibility
327
+ 3. Verify gem installation
328
+ 4. Test with staging environment first
329
+
330
+ ---
331
+
332
+ **🏛️💎 Ready to integrate court filing workflows with Tyler EFM using Ruby!**