io-complyance-unify-sdk 3.0.0
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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +26 -0
- data/README.md +595 -0
- data/lib/complyance/circuit_breaker.rb +99 -0
- data/lib/complyance/persistent_queue_manager.rb +474 -0
- data/lib/complyance/retry_strategy.rb +198 -0
- data/lib/complyance_sdk/config/retry_config.rb +127 -0
- data/lib/complyance_sdk/config/sdk_config.rb +212 -0
- data/lib/complyance_sdk/exceptions/circuit_breaker_open_error.rb +14 -0
- data/lib/complyance_sdk/exceptions/sdk_exception.rb +93 -0
- data/lib/complyance_sdk/generators/config_generator.rb +67 -0
- data/lib/complyance_sdk/generators/install_generator.rb +22 -0
- data/lib/complyance_sdk/generators/templates/complyance_initializer.rb +36 -0
- data/lib/complyance_sdk/http/authentication_middleware.rb +43 -0
- data/lib/complyance_sdk/http/client.rb +223 -0
- data/lib/complyance_sdk/http/logging_middleware.rb +153 -0
- data/lib/complyance_sdk/jobs/base_job.rb +63 -0
- data/lib/complyance_sdk/jobs/process_document_job.rb +92 -0
- data/lib/complyance_sdk/jobs/sidekiq_job.rb +165 -0
- data/lib/complyance_sdk/middleware/rack_middleware.rb +39 -0
- data/lib/complyance_sdk/models/country.rb +205 -0
- data/lib/complyance_sdk/models/country_policy_registry.rb +159 -0
- data/lib/complyance_sdk/models/document_type.rb +52 -0
- data/lib/complyance_sdk/models/environment.rb +144 -0
- data/lib/complyance_sdk/models/logical_doc_type.rb +228 -0
- data/lib/complyance_sdk/models/mode.rb +47 -0
- data/lib/complyance_sdk/models/operation.rb +47 -0
- data/lib/complyance_sdk/models/policy_result.rb +145 -0
- data/lib/complyance_sdk/models/purpose.rb +52 -0
- data/lib/complyance_sdk/models/source.rb +104 -0
- data/lib/complyance_sdk/models/source_ref.rb +130 -0
- data/lib/complyance_sdk/models/unify_request.rb +208 -0
- data/lib/complyance_sdk/models/unify_response.rb +198 -0
- data/lib/complyance_sdk/queue/persistent_queue_manager.rb +609 -0
- data/lib/complyance_sdk/railtie.rb +29 -0
- data/lib/complyance_sdk/retry/circuit_breaker.rb +159 -0
- data/lib/complyance_sdk/retry/retry_manager.rb +108 -0
- data/lib/complyance_sdk/retry/retry_strategy.rb +225 -0
- data/lib/complyance_sdk/version.rb +5 -0
- data/lib/complyance_sdk.rb +935 -0
- metadata +322 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 1575651fce5572033d2f3f37d21415f5169ebc19e78e529b131cd4c8c913c118
|
|
4
|
+
data.tar.gz: 48df40480ed94d3404d81774a4d5430e1af1215cd7eb183af939fc8691a736a3
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: e34ae01a956b530b3bae80f5362343d3f2f376326c64e7276b7397c4fc68233a53e5243908eb25329998d42a39a72a34bf140ab153cb842ea6d01328b7f49b3b
|
|
7
|
+
data.tar.gz: cb00a9fce2808f4be795565e65103bb5e10323e31f77d80635142c5d88f0b6949ef7b344dd6b62a3704939df1ce4cf01971341031f1bf6213d14827eee7755e6
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Initial Ruby SDK implementation
|
|
13
|
+
- Configuration system with environment variable and Rails credentials support
|
|
14
|
+
- Basic gem structure with proper gemspec
|
|
15
|
+
- Rails integration with Railtie and generators
|
|
16
|
+
- Exception handling system
|
|
17
|
+
- Source and Environment models
|
|
18
|
+
- Retry configuration system
|
|
19
|
+
|
|
20
|
+
## [0.1.0] - 2024-01-XX
|
|
21
|
+
|
|
22
|
+
### Added
|
|
23
|
+
|
|
24
|
+
- Initial release of ComplyanceSDK for Ruby
|
|
25
|
+
- Basic SDK structure and configuration
|
|
26
|
+
- Rails integration support
|
data/README.md
ADDED
|
@@ -0,0 +1,595 @@
|
|
|
1
|
+
# GETS Ruby SDK
|
|
2
|
+
|
|
3
|
+
A Ruby SDK for integrating with the GETS Unify e-invoicing platform. This SDK provides easy-to-use APIs for document submission, payload processing, and multi-country compliance management.
|
|
4
|
+
|
|
5
|
+
## 🚀 **What Actually Works**
|
|
6
|
+
|
|
7
|
+
- ✅ **Simple API Configuration** - Minimal setup required
|
|
8
|
+
- ✅ **Type-safe Enums** - DocumentType, Country, Environment, etc.
|
|
9
|
+
- ✅ **Basic Status Helpers** - Check submission states
|
|
10
|
+
- ✅ **Comprehensive Error Handling** - Detailed error messages with suggestions
|
|
11
|
+
- ✅ **HTTP Client** - Robust API communication with timeout handling
|
|
12
|
+
- ✅ **Request/Response Parsing** - Full UnifyResponse structure matching backend
|
|
13
|
+
- ✅ **Retry Detection** - Automatic detection of retryable errors
|
|
14
|
+
- ✅ **Logging** - Comprehensive logging with different levels
|
|
15
|
+
- ✅ **Persistent Queue Manager** - File-based retry queue for failed submissions
|
|
16
|
+
- ✅ **Circuit Breaker** - Prevents cascading failures
|
|
17
|
+
- ✅ **Logical Document Types** - Business-level document classification
|
|
18
|
+
- ✅ **Country Policy Registry** - Country-specific validation rules
|
|
19
|
+
- ✅ **Source Reference** - Simplified source identity management
|
|
20
|
+
|
|
21
|
+
## 📋 **Current Limitations**
|
|
22
|
+
|
|
23
|
+
- ⚠️ **Template Management** - Handled server-side (not SDK responsibility)
|
|
24
|
+
- ⚠️ **Limited Countries** - Currently supports SA (Saudi Arabia) and MY (Malaysia) in production
|
|
25
|
+
- ⚠️ **Basic Retry Logic** - File-based queue retry (can be enhanced)
|
|
26
|
+
|
|
27
|
+
## Installation
|
|
28
|
+
|
|
29
|
+
Add this line to your application's Gemfile:
|
|
30
|
+
|
|
31
|
+
```ruby
|
|
32
|
+
gem 'complyance_sdk'
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
And then execute:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
$ bundle install
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Or install it yourself as:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
$ gem install complyance_sdk
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Quick Start
|
|
48
|
+
|
|
49
|
+
### 1. Add Dependency
|
|
50
|
+
|
|
51
|
+
Add to your `Gemfile`:
|
|
52
|
+
|
|
53
|
+
```ruby
|
|
54
|
+
gem 'complyance_sdk'
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### 2. Configuration
|
|
58
|
+
|
|
59
|
+
```ruby
|
|
60
|
+
# Configure sources and SDK
|
|
61
|
+
source = ComplyanceSDK::Models::Source.new(
|
|
62
|
+
type: :first_party,
|
|
63
|
+
id: "ERP-1",
|
|
64
|
+
name: "SAP ERP",
|
|
65
|
+
version: "2024.1"
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
ComplyanceSDK.configure do |config|
|
|
69
|
+
config.api_key = "YOUR_API_KEY"
|
|
70
|
+
config.environment = :sandbox
|
|
71
|
+
config.add_source(source)
|
|
72
|
+
|
|
73
|
+
# Enhanced retry configuration with circuit breaker
|
|
74
|
+
config.retry_config = ComplyanceSDK::Config::RetryConfig.new(
|
|
75
|
+
max_attempts: 5,
|
|
76
|
+
base_delay: 1000, # milliseconds
|
|
77
|
+
backoff_multiplier: 2.0,
|
|
78
|
+
circuit_breaker_enabled: true
|
|
79
|
+
)
|
|
80
|
+
end
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### 3. Simple Invoice Submission with Logical Document Types
|
|
84
|
+
|
|
85
|
+
```ruby
|
|
86
|
+
# Simple invoice submission - automatically routes to tax authority
|
|
87
|
+
payload = {
|
|
88
|
+
invoice_data: {
|
|
89
|
+
invoice_number: "INV-123",
|
|
90
|
+
total_amount: 1000,
|
|
91
|
+
customer_name: "Acme Corp"
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
begin
|
|
96
|
+
response = ComplyanceSDK.push_to_unify_logical(
|
|
97
|
+
"ERP-1", # Source name
|
|
98
|
+
"2024.1", # Source version
|
|
99
|
+
:tax_invoice_export_invoice, # Logical document type
|
|
100
|
+
:sa, # Country
|
|
101
|
+
:single, # Operation
|
|
102
|
+
:documents, # Mode
|
|
103
|
+
:invoicing, # Purpose
|
|
104
|
+
payload # Business data
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
if response[:status] == 'success'
|
|
108
|
+
puts "✅ Invoice processed successfully!"
|
|
109
|
+
|
|
110
|
+
# Access the rich response data
|
|
111
|
+
if response[:data]
|
|
112
|
+
# Check payload storage
|
|
113
|
+
if response[:data][:payload]
|
|
114
|
+
puts "Payload ID: #{response[:data][:payload][:payload_id]}"
|
|
115
|
+
puts "Stored at: #{response[:data][:payload][:stored_at]}"
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# Check template mapping
|
|
119
|
+
if response[:data][:template]
|
|
120
|
+
puts "Template: #{response[:data][:template][:template_name]}"
|
|
121
|
+
puts "Mapping completed: #{response[:data][:template][:mapping_completed]}"
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# Check document creation (only for purpose="invoicing")
|
|
125
|
+
if response[:data][:document]
|
|
126
|
+
puts "Document ID: #{response[:data][:document][:document_id]}"
|
|
127
|
+
puts "Created at: #{response[:data][:document][:created_at]}"
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
# Check government submission (only for purpose="invoicing")
|
|
131
|
+
if response[:data][:submission]
|
|
132
|
+
puts "Submission status: #{response[:data][:submission][:status]}"
|
|
133
|
+
puts "Authority: #{response[:data][:submission][:authority]}"
|
|
134
|
+
|
|
135
|
+
if response[:data][:submission][:accepted]
|
|
136
|
+
puts "✅ Successfully submitted to #{response[:data][:submission][:authority]}"
|
|
137
|
+
|
|
138
|
+
# Access government response data
|
|
139
|
+
if response[:data][:submission][:response]
|
|
140
|
+
puts "UUID: #{response[:data][:submission][:response][:uuid]}"
|
|
141
|
+
puts "QR Code: #{response[:data][:submission][:response][:qr_code]}"
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
rescue ComplyanceSDK::Exceptions::SDKException => e
|
|
148
|
+
handle_error(e)
|
|
149
|
+
end
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### 4. Create Mapping Only
|
|
153
|
+
|
|
154
|
+
```ruby
|
|
155
|
+
# Create mapping template (no full invoice processing)
|
|
156
|
+
payload = {
|
|
157
|
+
invoice_data: {
|
|
158
|
+
invoice_id: "INV-001",
|
|
159
|
+
total_amount: 1500.00,
|
|
160
|
+
customer_name: "Acme Corp"
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
begin
|
|
165
|
+
response = ComplyanceSDK.create_mapping_logical(
|
|
166
|
+
"ERP-1", # Source name
|
|
167
|
+
"2024.1", # Source version
|
|
168
|
+
:sa, # Country
|
|
169
|
+
:tax_invoice, # Logical document type
|
|
170
|
+
payload # Sample data
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
if response[:status] == 'success' && response[:data]
|
|
174
|
+
puts "✅ Mapping created successfully!"
|
|
175
|
+
|
|
176
|
+
if response[:data][:template]
|
|
177
|
+
puts "Template ID: #{response[:data][:template][:template_id]}"
|
|
178
|
+
puts "Mapping completed: #{response[:data][:template][:mapping_completed]}"
|
|
179
|
+
puts "Mandatory fields mapped: #{response[:data][:template][:mapped_mandatory_fields]}/#{response[:data][:template][:total_mandatory_fields]}"
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
rescue ComplyanceSDK::Exceptions::SDKException => e
|
|
183
|
+
handle_error(e)
|
|
184
|
+
end
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
## 🎯 **Advanced Usage**
|
|
188
|
+
|
|
189
|
+
### Custom Destinations
|
|
190
|
+
|
|
191
|
+
```ruby
|
|
192
|
+
# Submit with custom destinations
|
|
193
|
+
destinations = [
|
|
194
|
+
# Send to tax authority
|
|
195
|
+
{
|
|
196
|
+
type: :tax_authority,
|
|
197
|
+
country: "SA",
|
|
198
|
+
authority: "ZATCA",
|
|
199
|
+
document_type: "tax_invoice"
|
|
200
|
+
},
|
|
201
|
+
|
|
202
|
+
# Send email notification
|
|
203
|
+
{
|
|
204
|
+
type: :email,
|
|
205
|
+
recipients: ["finance@company.com"],
|
|
206
|
+
subject: "Invoice INV-123 Submitted",
|
|
207
|
+
message: "Your invoice has been successfully submitted to ZATCA"
|
|
208
|
+
},
|
|
209
|
+
|
|
210
|
+
# Archive for storage
|
|
211
|
+
{ type: :archive }
|
|
212
|
+
]
|
|
213
|
+
|
|
214
|
+
response = ComplyanceSDK.push_to_unify_logical(
|
|
215
|
+
"ERP-1", # Source name
|
|
216
|
+
"2024.1", # Source version
|
|
217
|
+
:tax_invoice, # Logical document type
|
|
218
|
+
:sa, # Country
|
|
219
|
+
:single, # Operation
|
|
220
|
+
:documents, # Mode
|
|
221
|
+
:invoicing, # Purpose
|
|
222
|
+
payload, # Business data
|
|
223
|
+
destinations # Custom destinations
|
|
224
|
+
)
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### Comprehensive Error Handling
|
|
228
|
+
|
|
229
|
+
```ruby
|
|
230
|
+
def handle_error(exception)
|
|
231
|
+
error_detail = exception.context || {}
|
|
232
|
+
|
|
233
|
+
puts "❌ Error Code: #{error_detail[:code]}"
|
|
234
|
+
puts "❌ Message: #{exception.message}"
|
|
235
|
+
|
|
236
|
+
# Show suggestion if available
|
|
237
|
+
if error_detail[:suggestion]
|
|
238
|
+
puts "💡 Suggestion: #{error_detail[:suggestion]}"
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
# Show documentation link if available
|
|
242
|
+
if error_detail[:documentation_url]
|
|
243
|
+
puts "📖 Documentation: #{error_detail[:documentation_url]}"
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
# Show field-specific error if available
|
|
247
|
+
if error_detail[:field]
|
|
248
|
+
puts "🎯 Field: #{error_detail[:field]}"
|
|
249
|
+
if error_detail[:field_value]
|
|
250
|
+
puts "🎯 Value: #{error_detail[:field_value]}"
|
|
251
|
+
end
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
# Show validation errors if available
|
|
255
|
+
if error_detail[:validation_errors] && !error_detail[:validation_errors].empty?
|
|
256
|
+
puts "📝 Validation Errors:"
|
|
257
|
+
error_detail[:validation_errors].each do |validation_error|
|
|
258
|
+
puts " - #{validation_error[:field]}: #{validation_error[:message]}"
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
# Check if error is retryable
|
|
263
|
+
if error_detail[:retryable]
|
|
264
|
+
puts "🔄 This error can be retried"
|
|
265
|
+
if error_detail[:retry_after_seconds]
|
|
266
|
+
puts "⏱️ Retry after: #{error_detail[:retry_after_seconds]} seconds"
|
|
267
|
+
end
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
# Show additional context if available
|
|
271
|
+
if error_detail[:context] && !error_detail[:context].empty?
|
|
272
|
+
puts "📋 Additional Context:"
|
|
273
|
+
error_detail[:context].each do |key, value|
|
|
274
|
+
puts " #{key}: #{value}"
|
|
275
|
+
end
|
|
276
|
+
end
|
|
277
|
+
end
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
### Handle Different Response Scenarios
|
|
281
|
+
|
|
282
|
+
```ruby
|
|
283
|
+
def process_response(response)
|
|
284
|
+
unless response[:status] == 'success'
|
|
285
|
+
puts "❌ Request failed: #{response[:message]}"
|
|
286
|
+
if response[:error]
|
|
287
|
+
handle_error(ComplyanceSDK::Exceptions::SDKException.new(response[:error][:message], context: response[:error]))
|
|
288
|
+
end
|
|
289
|
+
return
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
unless response[:data]
|
|
293
|
+
puts "⚠️ No data in response"
|
|
294
|
+
return
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
data = response[:data]
|
|
298
|
+
|
|
299
|
+
# Always present: source, payload, template, processing
|
|
300
|
+
puts "📦 Source: #{data[:source][:source_id]}"
|
|
301
|
+
puts "📄 Payload: #{data[:payload][:payload_id]}"
|
|
302
|
+
puts "🎨 Template: #{data[:template][:template_name]}"
|
|
303
|
+
puts "⚙️ Purpose: #{data[:processing][:purpose]}"
|
|
304
|
+
|
|
305
|
+
# Only for purpose="invoicing": conversion, document, validation, submission
|
|
306
|
+
if data[:processing][:purpose] == 'invoicing'
|
|
307
|
+
puts "📋 Full invoicing workflow completed"
|
|
308
|
+
|
|
309
|
+
if data[:conversion]
|
|
310
|
+
puts "🔄 Conversion: #{data[:conversion][:success] ? '✅' : '❌'}"
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
if data[:document]
|
|
314
|
+
puts "📄 Document: #{data[:document][:document_id]}"
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
if data[:validation]
|
|
318
|
+
puts "✅ Validation: #{data[:validation][:overall_success] ? '✅' : '❌'}"
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
if data[:submission]
|
|
322
|
+
puts "📤 Submission: #{data[:submission][:status]}"
|
|
323
|
+
end
|
|
324
|
+
else
|
|
325
|
+
puts "📋 Mapping-only workflow completed"
|
|
326
|
+
end
|
|
327
|
+
end
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
## 🔧 **Error Types & Handling**
|
|
331
|
+
|
|
332
|
+
The SDK provides detailed error information for different scenarios:
|
|
333
|
+
|
|
334
|
+
```ruby
|
|
335
|
+
# Validation errors
|
|
336
|
+
begin
|
|
337
|
+
ComplyanceSDK.push_to_unify_logical(...)
|
|
338
|
+
rescue ComplyanceSDK::Exceptions::ValidationError => e
|
|
339
|
+
if e.context[:code] == :validation_failed
|
|
340
|
+
# Handle validation errors - check field values
|
|
341
|
+
end
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
# Authentication errors
|
|
345
|
+
begin
|
|
346
|
+
ComplyanceSDK.push_to_unify_logical(...)
|
|
347
|
+
rescue ComplyanceSDK::Exceptions::SDKException => e
|
|
348
|
+
if e.context[:code] == :authentication_failed
|
|
349
|
+
# Handle auth errors - check API key
|
|
350
|
+
end
|
|
351
|
+
end
|
|
352
|
+
|
|
353
|
+
# Country-specific errors
|
|
354
|
+
begin
|
|
355
|
+
ComplyanceSDK.push_to_unify_logical(...)
|
|
356
|
+
rescue ComplyanceSDK::Exceptions::ValidationError => e
|
|
357
|
+
if e.context[:code] == :zatca_validation_failed
|
|
358
|
+
# Handle Saudi Arabia specific validation errors
|
|
359
|
+
end
|
|
360
|
+
end
|
|
361
|
+
|
|
362
|
+
# Network/API errors (retryable)
|
|
363
|
+
begin
|
|
364
|
+
ComplyanceSDK.push_to_unify_logical(...)
|
|
365
|
+
rescue ComplyanceSDK::Exceptions::SDKException => e
|
|
366
|
+
if e.context[:retryable]
|
|
367
|
+
# Implement retry logic
|
|
368
|
+
retry_after = e.context[:retry_after_seconds]
|
|
369
|
+
# Wait and retry
|
|
370
|
+
end
|
|
371
|
+
end
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
## 📊 **Response Structure**
|
|
375
|
+
|
|
376
|
+
The SDK properly parses the complete backend response:
|
|
377
|
+
|
|
378
|
+
```ruby
|
|
379
|
+
response = ComplyanceSDK.push_to_unify_logical(...)
|
|
380
|
+
|
|
381
|
+
# Main response
|
|
382
|
+
response[:status] # "success" or "error"
|
|
383
|
+
response[:message] # Response message
|
|
384
|
+
response[:data] # Response data (nil if error)
|
|
385
|
+
|
|
386
|
+
# Response data
|
|
387
|
+
response[:data][:source] # Source information
|
|
388
|
+
response[:data][:payload] # Payload storage info
|
|
389
|
+
response[:data][:template] # Template mapping info
|
|
390
|
+
response[:data][:processing] # Processing metadata
|
|
391
|
+
|
|
392
|
+
# Only for purpose="invoicing"
|
|
393
|
+
response[:data][:conversion] # Conversion results
|
|
394
|
+
response[:data][:document] # Document creation
|
|
395
|
+
response[:data][:validation] # Validation results
|
|
396
|
+
response[:data][:submission] # Government submission
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
## 🔄 **Queue Management**
|
|
400
|
+
|
|
401
|
+
The Ruby SDK includes a persistent queue manager for handling failed submissions:
|
|
402
|
+
|
|
403
|
+
```ruby
|
|
404
|
+
# Get queue status
|
|
405
|
+
status = ComplyanceSDK.queue_status
|
|
406
|
+
puts "Pending: #{status[:pending_count]}"
|
|
407
|
+
puts "Processing: #{status[:processing_count]}"
|
|
408
|
+
puts "Failed: #{status[:failed_count]}"
|
|
409
|
+
puts "Success: #{status[:success_count]}"
|
|
410
|
+
|
|
411
|
+
# Retry failed submissions
|
|
412
|
+
ComplyanceSDK.retry_failed_submissions
|
|
413
|
+
|
|
414
|
+
# Process pending submissions manually
|
|
415
|
+
ComplyanceSDK.process_pending_submissions
|
|
416
|
+
|
|
417
|
+
# Clean up old success files (keep last 7 days)
|
|
418
|
+
ComplyanceSDK.cleanup_old_success_files(7)
|
|
419
|
+
|
|
420
|
+
# Emergency cleanup - clear all queues
|
|
421
|
+
ComplyanceSDK.clear_all_queues
|
|
422
|
+
|
|
423
|
+
# Clean up duplicate files
|
|
424
|
+
ComplyanceSDK.cleanup_duplicate_files
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
## 🧪 **Testing Your Integration**
|
|
428
|
+
|
|
429
|
+
```ruby
|
|
430
|
+
require 'rspec'
|
|
431
|
+
|
|
432
|
+
RSpec.describe "Invoice Submission" do
|
|
433
|
+
before do
|
|
434
|
+
# Configure SDK for testing
|
|
435
|
+
source = ComplyanceSDK::Models::Source.new(
|
|
436
|
+
type: :first_party,
|
|
437
|
+
id: "TEST-1",
|
|
438
|
+
name: "Test Source",
|
|
439
|
+
version: "1.0"
|
|
440
|
+
)
|
|
441
|
+
|
|
442
|
+
ComplyanceSDK.configure do |config|
|
|
443
|
+
config.api_key = "test-api-key"
|
|
444
|
+
config.environment = :sandbox
|
|
445
|
+
config.add_source(source)
|
|
446
|
+
end
|
|
447
|
+
end
|
|
448
|
+
|
|
449
|
+
it "successfully submits an invoice" do
|
|
450
|
+
# Prepare payload
|
|
451
|
+
payload = {
|
|
452
|
+
invoice_data: {
|
|
453
|
+
invoice_number: "TEST-001",
|
|
454
|
+
total_amount: 100.00,
|
|
455
|
+
currency: "SAR"
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
# Submit and verify
|
|
460
|
+
response = ComplyanceSDK.submit_invoice_logical(
|
|
461
|
+
"TEST-1", "1.0", :sa, :tax_invoice, payload
|
|
462
|
+
)
|
|
463
|
+
|
|
464
|
+
expect(response[:status]).to eq('success')
|
|
465
|
+
expect(response[:data]).not_to be_nil
|
|
466
|
+
expect(response[:data][:payload][:payload_id]).not_to be_nil
|
|
467
|
+
end
|
|
468
|
+
|
|
469
|
+
it "handles validation errors" do
|
|
470
|
+
# Test invalid payload
|
|
471
|
+
invalid_payload = {} # Empty payload
|
|
472
|
+
|
|
473
|
+
expect {
|
|
474
|
+
ComplyanceSDK.submit_invoice_logical(
|
|
475
|
+
"TEST-1", "1.0", :sa, :tax_invoice, invalid_payload
|
|
476
|
+
)
|
|
477
|
+
}.to raise_error(ComplyanceSDK::Exceptions::ValidationError)
|
|
478
|
+
end
|
|
479
|
+
end
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
## Environment Variables
|
|
483
|
+
|
|
484
|
+
```ruby
|
|
485
|
+
# Configure from environment variables
|
|
486
|
+
ComplyanceSDK.configure_from_env
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
Required environment variables:
|
|
490
|
+
|
|
491
|
+
- `COMPLYANCE_API_KEY`: Your API key
|
|
492
|
+
- `COMPLYANCE_ENVIRONMENT`: Environment (dev, test, stage, local, sandbox, simulation, production)
|
|
493
|
+
|
|
494
|
+
Optional environment variables:
|
|
495
|
+
|
|
496
|
+
- `COMPLYANCE_LOGGING_ENABLED`: Enable or disable logging (true, false)
|
|
497
|
+
- `COMPLYANCE_LOG_LEVEL`: Log level (debug, info, warn, error)
|
|
498
|
+
|
|
499
|
+
## Rails Integration
|
|
500
|
+
|
|
501
|
+
In a Rails application, the SDK can be configured using Rails credentials:
|
|
502
|
+
|
|
503
|
+
```ruby
|
|
504
|
+
# config/initializers/complyance_sdk.rb
|
|
505
|
+
ComplyanceSDK.configure_from_rails
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
Add your API key to your credentials:
|
|
509
|
+
|
|
510
|
+
```yaml
|
|
511
|
+
# rails credentials:edit
|
|
512
|
+
complyance:
|
|
513
|
+
api_key: your_api_key_here
|
|
514
|
+
environment: sandbox
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
Or use environment-specific credentials:
|
|
518
|
+
|
|
519
|
+
```yaml
|
|
520
|
+
complyance:
|
|
521
|
+
development:
|
|
522
|
+
api_key: your_development_api_key
|
|
523
|
+
environment: sandbox
|
|
524
|
+
production:
|
|
525
|
+
api_key: your_production_api_key
|
|
526
|
+
environment: production
|
|
527
|
+
```
|
|
528
|
+
|
|
529
|
+
## 📚 **API Reference**
|
|
530
|
+
|
|
531
|
+
### Core Methods
|
|
532
|
+
|
|
533
|
+
- `ComplyanceSDK.configure(config)` - Initialize SDK
|
|
534
|
+
- `ComplyanceSDK.push_to_unify_logical(...)` - Complete workflow with logical document types
|
|
535
|
+
- `ComplyanceSDK.submit_invoice_logical(...)` - Complete invoicing workflow
|
|
536
|
+
- `ComplyanceSDK.create_mapping_logical(...)` - Create mapping templates only
|
|
537
|
+
- `ComplyanceSDK.push_to_unify_with_source_ref(...)` - Full control with SourceRef
|
|
538
|
+
|
|
539
|
+
### Helper Methods
|
|
540
|
+
|
|
541
|
+
- `response[:status] == 'success'` - Check if request succeeded
|
|
542
|
+
- `response[:error]` - Check if request has errors
|
|
543
|
+
- `submission[:accepted]` - Check if government accepted submission
|
|
544
|
+
- `processing[:purpose] == 'invoicing'` - Check if full invoicing workflow
|
|
545
|
+
|
|
546
|
+
### Error Handling
|
|
547
|
+
|
|
548
|
+
- `error[:retryable]` - Check if error can be retried
|
|
549
|
+
- `error[:suggestion]` - Get helpful suggestion
|
|
550
|
+
- `error[:validation_errors]` - Get field-level validation errors
|
|
551
|
+
|
|
552
|
+
### Queue Management
|
|
553
|
+
|
|
554
|
+
- `ComplyanceSDK.queue_status` - Get queue statistics
|
|
555
|
+
- `ComplyanceSDK.retry_failed_submissions` - Retry failed submissions
|
|
556
|
+
- `ComplyanceSDK.process_pending_submissions` - Process pending submissions manually
|
|
557
|
+
- `ComplyanceSDK.clear_all_queues` - Emergency cleanup
|
|
558
|
+
|
|
559
|
+
For detailed documentation and examples, visit [https://docs.complyance.io](https://docs.complyance.io)
|
|
560
|
+
|
|
561
|
+
---
|
|
562
|
+
|
|
563
|
+
## 🎯 **What's Next?**
|
|
564
|
+
|
|
565
|
+
This SDK provides a solid foundation for e-invoicing integration with:
|
|
566
|
+
|
|
567
|
+
- ✅ Proper request/response handling
|
|
568
|
+
- ✅ Comprehensive error management
|
|
569
|
+
- ✅ Rich response parsing
|
|
570
|
+
- ✅ Type-safe operations
|
|
571
|
+
- ✅ Persistent queue management
|
|
572
|
+
- ✅ Circuit breaker pattern
|
|
573
|
+
- ✅ Logical document types
|
|
574
|
+
- ✅ Country-specific validation
|
|
575
|
+
|
|
576
|
+
Future enhancements may include:
|
|
577
|
+
|
|
578
|
+
- 🔄 Redis-based retry strategies
|
|
579
|
+
- 🌍 Extended country support
|
|
580
|
+
- 🔒 Enhanced security features
|
|
581
|
+
- 📊 Built-in analytics and monitoring
|
|
582
|
+
|
|
583
|
+
## Development
|
|
584
|
+
|
|
585
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
|
586
|
+
|
|
587
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
|
588
|
+
|
|
589
|
+
## Contributing
|
|
590
|
+
|
|
591
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/complyance-io/sdk-ruby.
|
|
592
|
+
|
|
593
|
+
## License
|
|
594
|
+
|
|
595
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|