Module: ComplyanceSDK

Defined in:
lib/complyance_sdk.rb,
lib/complyance_sdk/railtie.rb,
lib/complyance_sdk/version.rb,
lib/complyance_sdk/erp/client.rb,
lib/complyance_sdk/http/client.rb,
lib/complyance_sdk/models/mode.rb,
lib/complyance_sdk/jobs/base_job.rb,
lib/complyance_sdk/models/source.rb,
lib/complyance_sdk/models/country.rb,
lib/complyance_sdk/models/purpose.rb,
lib/complyance_sdk/jobs/sidekiq_job.rb,
lib/complyance_sdk/models/operation.rb,
lib/complyance_sdk/config/sdk_config.rb,
lib/complyance_sdk/models/source_ref.rb,
lib/complyance_sdk/onboarding/client.rb,
lib/complyance_sdk/models/environment.rb,
lib/complyance_sdk/config/retry_config.rb,
lib/complyance_sdk/retry/retry_manager.rb,
lib/complyance_sdk/models/document_type.rb,
lib/complyance_sdk/models/policy_result.rb,
lib/complyance_sdk/models/unify_request.rb,
lib/complyance_sdk/retry/retry_strategy.rb,
lib/complyance_sdk/models/unify_response.rb,
lib/complyance_sdk/retry/circuit_breaker.rb,
lib/complyance_sdk/http/logging_middleware.rb,
lib/complyance_sdk/models/logical_doc_type.rb,
lib/complyance_sdk/purchase_invoice/models.rb,
lib/complyance_sdk/exceptions/sdk_exception.rb,
lib/complyance_sdk/jobs/process_document_job.rb,
lib/complyance_sdk/middleware/rack_middleware.rb,
lib/complyance_sdk/generators/config_generator.rb,
lib/complyance_sdk/generators/install_generator.rb,
lib/complyance_sdk/models/gets_document_type_v2.rb,
lib/complyance_sdk/http/authentication_middleware.rb,
lib/complyance_sdk/models/country_policy_registry.rb,
lib/complyance_sdk/models/logical_doc_type_mapper.rb,
lib/complyance_sdk/queue/persistent_queue_manager.rb,
lib/complyance_sdk/exceptions/circuit_breaker_open_error.rb

Overview

Main module for the Complyance SDK

Defined Under Namespace

Modules: Config, ERP, Exceptions, Generators, HTTP, Jobs, Middleware, Models, Onboarding, PurchaseInvoice, Queue, Retry Classes: Railtie

Constant Summary collapse

VERSION =
"3.0.10"

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.configurationObject

Returns the value of attribute configuration.



37
38
39
# File 'lib/complyance_sdk.rb', line 37

def configuration
  @configuration
end

Class Method Details

.cleanup_duplicate_filesObject

Clean up duplicate files across queue directories



666
667
668
669
670
671
672
# File 'lib/complyance_sdk.rb', line 666

def cleanup_duplicate_files
  if queue_manager
    queue_manager.cleanup_duplicate_files
  else
    raise ComplyanceSDK::Exceptions::ConfigurationError.new("Queue Manager is not initialized")
  end
end

.cleanup_old_success_files(days_to_keep) ⇒ Object

Clean up old success files

Parameters:

  • days_to_keep (Integer)

    Number of days to keep success files



652
653
654
# File 'lib/complyance_sdk.rb', line 652

def cleanup_old_success_files(days_to_keep)
  queue_manager&.cleanup_old_success_files(days_to_keep)
end

.clear_all_queuesObject

Clear all files from the queue (emergency cleanup)



657
658
659
660
661
662
663
# File 'lib/complyance_sdk.rb', line 657

def clear_all_queues
  if queue_manager
    queue_manager.clear_all_queues
  else
    raise ComplyanceSDK::Exceptions::ConfigurationError.new("Queue Manager is not initialized")
  end
end

.configure(config = nil) {|config| ... } ⇒ ComplyanceSDK::Config::SDKConfig

Configure the SDK with the provided configuration

Parameters:

Yields:

  • (config)

    Yields the configuration object for block-style configuration

Returns:



44
45
46
47
48
49
50
51
52
53
# File 'lib/complyance_sdk.rb', line 44

def configure(config = nil)
  self.configuration = config if config.is_a?(ComplyanceSDK::Config::SDKConfig)
  
  if block_given?
    self.configuration ||= ComplyanceSDK::Config::SDKConfig.new
    yield(configuration)
  end
  
  configuration
end

.configure_from_envComplyanceSDK::Config::SDKConfig

Configure the SDK from environment variables

Returns:



58
59
60
# File 'lib/complyance_sdk.rb', line 58

def configure_from_env
  self.configuration = ComplyanceSDK::Config::SDKConfig.from_env
end

.configure_from_rails(environment = nil) ⇒ ComplyanceSDK::Config::SDKConfig

Configure the SDK from Rails credentials

Parameters:

  • environment (Symbol) (defaults to: nil)

    The Rails environment (:development, :production, etc.)

Returns:



66
67
68
# File 'lib/complyance_sdk.rb', line 66

def configure_from_rails(environment = nil)
  self.configuration = ComplyanceSDK::Config::SDKConfig.from_rails(environment)
end

.configured?Boolean

Check if the SDK is configured

Returns:

  • (Boolean)

    True if the SDK is configured, false otherwise



73
74
75
# File 'lib/complyance_sdk.rb', line 73

def configured?
  !configuration.nil? && configuration.valid?
end

.create_mapping(options = {}) ⇒ ComplyanceSDK::Models::UnifyResponse

Convenience method for creating field mappings

Parameters:

  • options (Hash) (defaults to: {})

    Mapping options

Options Hash (options):

  • :country (String)

    Country code

  • :payload (Hash)

    Sample payload for mapping

  • :source (ComplyanceSDK::Models::Source)

    Source information

  • :document_type (Symbol)

    Document type (default: :tax_invoice)

Returns:



332
333
334
335
336
337
338
339
340
341
342
343
344
# File 'lib/complyance_sdk.rb', line 332

def create_mapping(options = {})
  request = ComplyanceSDK::Models::UnifyRequest.new(
    source: options[:source] || default_source,
    document_type: options[:document_type] || :tax_invoice,
    country: options[:country],
    operation: :single,
    mode: :documents,
    purpose: :mapping,
    payload: options[:payload]
  )

  push_to_unify(request)
end

.create_mapping_logical(source_name, source_version, country, logical_type, payload) ⇒ ComplyanceSDK::Models::UnifyResponse

Convenience method to create mappings with logical document types

Parameters:

  • source_name (String)

    The source name

  • source_version (String)

    The source version

  • country (Symbol)

    The country code

  • logical_type (Symbol)

    The logical document type

  • payload (Hash)

    The business data payload

Returns:



605
606
607
608
609
610
611
612
613
614
615
616
# File 'lib/complyance_sdk.rb', line 605

def create_mapping_logical(source_name, source_version, country, logical_type, payload)
  push_to_unify_logical(
    source_name,
    source_version,
    logical_type,
    country,
    :single,
    :documents,
    :mapping,
    payload
  )
end

.detailed_queue_statusHash

Get detailed queue status

Returns:

  • (Hash)

    Detailed queue status information



632
633
634
# File 'lib/complyance_sdk.rb', line 632

def detailed_queue_status
  queue_manager ? queue_manager.queue_status_detailed : { error: "Queue Manager is not initialized" }
end

.drain_queue(timeout_seconds = 30) ⇒ Object



687
688
689
# File 'lib/complyance_sdk.rb', line 687

def drain_queue(timeout_seconds = 30)
  queue_manager ? queue_manager.drain_queue(timeout_seconds) : true
end

.get_document_status(document_id) ⇒ Hash

Get retrieval status by document ID.

Parameters:

  • document_id (String)

    The document ID

Returns:

  • (Hash)

    Raw retrieval response hash



350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
# File 'lib/complyance_sdk.rb', line 350

def get_document_status(document_id)
  unless configured?
    raise ComplyanceSDK::Exceptions::ConfigurationError.new(
      "SDK must be configured before making API calls"
    )
  end

  normalized = document_id.to_s.strip
  if normalized.empty?
    raise ComplyanceSDK::Exceptions::ValidationError.new(
      "Document ID is required",
      suggestion: "Provide a valid documentId to fetch retrieval status."
    )
  end

  with_retry("get_document_status", { document_id: normalized }) do
    http_client.get("/api/v3/documents/#{URI.encode_www_form_component(normalized)}/status")
  end
end

.get_purchase_invoice(id) ⇒ Object



702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
# File 'lib/complyance_sdk.rb', line 702

def get_purchase_invoice(id)
  ensure_configured_for_purchase_api!

  if id.nil? || id.to_s.strip.empty?
    raise ComplyanceSDK::Exceptions::ValidationError.new(
      "Purchase invoice id is required",
      context: { suggestion: "Provide a valid purchase invoice id." }
    )
  end

  response = http_client.get(
    "/api/v3/documents/#{URI.encode_www_form_component(id.to_s)}?type=purchases",
    {},
    purchase_invoice_headers
  )

  payload = if response.is_a?(Hash)
              response[:data] || response['data'] || response
            else
              response
            end

  ComplyanceSDK::PurchaseInvoice::PurchaseInvoiceResult.from_h(payload)
end

.get_status(submission_id) ⇒ Object

Deprecated.

Use get_document_status(document_id).



383
384
385
# File 'lib/complyance_sdk.rb', line 383

def get_status(submission_id)
  get_submission_status(submission_id)
end

.get_submission_status(submission_id) ⇒ Hash

Deprecated submissionId polling endpoint.

Parameters:

  • submission_id (String)

    The submission ID

Returns:

  • (Hash)

Raises:



374
375
376
377
378
379
380
# File 'lib/complyance_sdk.rb', line 374

def get_submission_status(submission_id)
  _unused = submission_id
  raise ComplyanceSDK::Exceptions::ValidationError.new(
    "submissionId status retrieval is no longer supported",
    suggestion: "Use get_document_status(document_id) for polling status and trace endpoints."
  )
end

.list_purchase_invoices(filters = {}) ⇒ Object



696
697
698
699
700
# File 'lib/complyance_sdk.rb', line 696

def list_purchase_invoices(filters = {})
  ensure_configured_for_purchase_api!
  query = { type: "purchases" }.merge(filters.reject { |_key, value| value.nil? })
  http_client.get("/api/v3/documents", query)
end

.onboardingObject



85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/complyance_sdk.rb', line 85

def onboarding
  unless configured?
    raise ComplyanceSDK::Exceptions::ConfigurationError.new(
      "SDK must be configured before using onboarding"
    )
  end

  ComplyanceSDK::Onboarding::Client.new(
    api_key: configuration.api_key,
    base_url: ComplyanceSDK::Models::Environment.base_url(configuration.environment)
  )
end

.pause_queue_processingObject



679
680
681
# File 'lib/complyance_sdk.rb', line 679

def pause_queue_processing
  queue_manager&.pause_processing
end

.process_pending_submissionsObject

Process pending submissions now



675
676
677
# File 'lib/complyance_sdk.rb', line 675

def process_pending_submissions
  queue_manager&.process_pending_submissions_now
end

.process_queued_submissions_firstObject

Process queued submissions before handling new requests



692
693
694
# File 'lib/complyance_sdk.rb', line 692

def process_queued_submissions_first
  queue_manager&.process_pending_submissions_now
end

.push_to_unify(*args) ⇒ ComplyanceSDK::Models::UnifyResponse

Main API method for document processing (Java-style signature)

Parameters:

  • source_name (String)

    The source name

  • source_version (String)

    The source version

  • logical_doc_type (Symbol)

    The logical document type

  • country (Symbol)

    The country code

  • operation (Symbol)

    The operation type

  • mode (Symbol)

    The mode

  • purpose (Symbol)

    The purpose

  • payload (Hash)

    The business data payload

  • destinations (Array, nil)

    Optional destinations (auto-generated if nil)

Returns:



126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/complyance_sdk.rb', line 126

def push_to_unify(*args)
  if args.length == 1 && (args[0].is_a?(Hash) || args[0].is_a?(ComplyanceSDK::Models::UnifyRequest))
    return push_to_unify_request(args[0])
  end

  if args.length < 8 || args.length > 9
    raise ArgumentError, "wrong number of arguments (given #{args.length}, expected 1 or 8..9)"
  end

  source_name, source_version, logical_doc_type, country, operation, mode, purpose, payload, destinations = args
  push_to_unify_logical(source_name, source_version, logical_doc_type, country, operation, mode, purpose, payload, destinations)
end

.push_to_unify_async(request, options = {}) ⇒ String, Object

Process a document asynchronously using background jobs

Parameters:

Options Hash (options):

  • :job_type (Symbol)

    Job type (:active_job or :sidekiq)

  • :callback_url (String)

    Optional callback URL

  • :callback_headers (Hash)

    Optional callback headers

Returns:

  • (String, Object)

    Job ID or job object



395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
# File 'lib/complyance_sdk.rb', line 395

def push_to_unify_async(request, options = {})
  unless configured?
    raise ComplyanceSDK::Exceptions::ConfigurationError.new(
      "SDK must be configured before making API calls"
    )
  end

  # Convert hash to UnifyRequest if needed
  if request.is_a?(Hash)
    request = ComplyanceSDK::Models::UnifyRequest.from_h(request)
  end

  # Validate the request
  unless request.valid?
    raise ComplyanceSDK::Exceptions::ValidationError.new(
      "Invalid request: #{request.errors.join(', ')}",
      context: { errors: request.errors }
    )
  end

  retry_manager.execute_async(
    request.to_h,
    job_type: options[:job_type] || :active_job,
    callback_url: options[:callback_url],
    callback_headers: options[:callback_headers] || {}
  )
end

.push_to_unify_from_json(source_name, source_version, logical_doc_type, country, operation, mode, purpose, json_payload, destinations = nil) ⇒ ComplyanceSDK::Models::UnifyResponse

Push to Unify API with logical document types using JSON string payload

Parameters:

  • source_name (String)

    The source name

  • source_version (String)

    The source version

  • logical_doc_type (Symbol)

    The logical document type

  • country (Symbol)

    The country code

  • operation (Symbol)

    The operation type

  • mode (Symbol)

    The mode

  • purpose (Symbol)

    The purpose

  • json_payload (String)

    The JSON string payload

  • destinations (Array, nil) (defaults to: nil)

    Optional destinations (auto-generated if nil)

Returns:



151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
# File 'lib/complyance_sdk.rb', line 151

def push_to_unify_from_json(source_name, source_version, logical_doc_type, country, operation, mode, purpose, json_payload, destinations = nil)
  if json_payload.nil? || json_payload.to_s.strip.empty?
    raise ComplyanceSDK::Exceptions::ValidationError.new(
      "Payload is required but was null or empty",
      context: { 
        suggestion: 'Provide a non-empty JSON payload string. Example: \'{"invoiceNumber":"INV-123","amount":1000}\''
      }
    )
  end

  begin
    require 'json'
    payload_hash = JSON.parse(json_payload)
    
    unless payload_hash.is_a?(Hash)
      raise ComplyanceSDK::Exceptions::ValidationError.new(
        "Failed to parse JSON payload: parsed result is not a hash",
        context: { 
          suggestion: 'Ensure the payload is valid JSON and represents an object structure. Example: \'{"invoiceNumber":"INV-123"}\''
        }
      )
    end

    push_to_unify(source_name, source_version, logical_doc_type, country, operation, mode, purpose, payload_hash, destinations)
  rescue JSON::ParserError => parse_error
    payload_snippet = json_payload.length > 100 ? json_payload[0..99] + '...' : json_payload
    raise ComplyanceSDK::Exceptions::ValidationError.new(
      "Failed to parse JSON payload: #{parse_error.message}",
      context: { 
        suggestion: 'Ensure the payload is valid JSON. Example: \'{"invoiceNumber":"INV-123","amount":1000}\'',
        payload_snippet: payload_snippet,
        parse_error: parse_error.message
      }
    )
  rescue ComplyanceSDK::Exceptions::ValidationError
    raise
  rescue StandardError => conversion_error
    raise ComplyanceSDK::Exceptions::ValidationError.new(
      "Failed to parse JSON payload: #{conversion_error.message}",
      context: { 
        suggestion: 'Ensure the payload is valid JSON. Example: \'{"invoiceNumber":"INV-123","amount":1000}\'',
        conversion_error: conversion_error.message
      }
    )
  end
end

.push_to_unify_from_object(source_name, source_version, logical_doc_type, country, operation, mode, purpose, payload_object, destinations = nil) ⇒ ComplyanceSDK::Models::UnifyResponse

Push to Unify API with logical document types using object payload

Parameters:

  • source_name (String)

    The source name

  • source_version (String)

    The source version

  • logical_doc_type (Symbol)

    The logical document type

  • country (Symbol)

    The country code

  • operation (Symbol)

    The operation type

  • mode (Symbol)

    The mode

  • purpose (Symbol)

    The purpose

  • payload_object (Object)

    The object payload (any object that responds to to_h or has instance variables)

  • destinations (Array, nil) (defaults to: nil)

    Optional destinations (auto-generated if nil)

Returns:



210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
# File 'lib/complyance_sdk.rb', line 210

def push_to_unify_from_object(source_name, source_version, logical_doc_type, country, operation, mode, purpose, payload_object, destinations = nil)
  if payload_object.nil?
    raise ComplyanceSDK::Exceptions::ValidationError.new(
      "Payload object is required but was nil",
      context: { 
        suggestion: "Provide a valid payload object. Example: {invoice_number: 'INV-123', amount: 1000}"
      }
    )
  end

  begin
    # Convert object to hash
    payload_hash = if payload_object.is_a?(Hash)
                     payload_object
                   elsif payload_object.respond_to?(:to_h)
                     payload_object.to_h
                   elsif payload_object.respond_to?(:instance_variables)
                     # Convert object instance variables to hash
                     hash = {}
                     payload_object.instance_variables.each do |var|
                       key = var.to_s.delete('@')
                       hash[key] = payload_object.instance_variable_get(var)
                     end
                     hash
                   else
                     # Try JSON serialization for other objects
                     require 'json'
                     json_str = payload_object.to_json
                     JSON.parse(json_str)
                   end

    unless payload_hash.is_a?(Hash)
      raise ComplyanceSDK::Exceptions::ValidationError.new(
        "Failed to convert payload object to hash: conversion returned invalid result",
        context: { 
          suggestion: "Ensure the object structure is compatible with the SDK payload format. " +
                     "The object should be convertible to a hash structure."
        }
      )
    end

    push_to_unify(source_name, source_version, logical_doc_type, country, operation, mode, purpose, payload_hash, destinations)
  rescue ComplyanceSDK::Exceptions::ValidationError
    raise
  rescue StandardError => conversion_error
    raise ComplyanceSDK::Exceptions::ValidationError.new(
      "Failed to convert payload object to hash: #{conversion_error.message}",
      context: { 
        suggestion: "Ensure the object structure is compatible with the SDK payload format. " +
                   "The object should be convertible to a hash. " +
                   "Example: {invoice_number: 'INV-123', amount: 1000} or a class with public attributes.",
        object_type: payload_object.class.name,
        conversion_error: conversion_error.message
      }
    )
  end
end

.push_to_unify_logical(source_name, source_version, logical_type, country, operation, mode, purpose, payload, destinations = nil) ⇒ ComplyanceSDK::Models::UnifyResponse

Push to Unify API with logical document types but full control over operation, mode, and purpose This is the primary method for all workflows with logical document types

Parameters:

  • source_name (String)

    The source name

  • source_version (String)

    The source version

  • logical_type (Symbol)

    The logical document type

  • country (Symbol)

    The country code

  • operation (Symbol)

    The operation type

  • mode (Symbol)

    The mode

  • purpose (Symbol)

    The purpose

  • payload (Hash)

    The business data payload

  • destinations (Array, nil) (defaults to: nil)

    Optional destinations (auto-generated if nil)

Returns:



436
437
438
439
440
441
442
443
# File 'lib/complyance_sdk.rb', line 436

def push_to_unify_logical(source_name, source_version, logical_type, country, operation, mode, purpose, payload, destinations = nil)
  validate_required_parameter(logical_type, :logical_type, "Logical document type is required")
  policy = ComplyanceSDK::Models::CountryPolicyRegistry.evaluate(country, logical_type)
  merged_payload = deep_merge_into_meta_config(payload, policy.meta_config_flags)
  set_invoice_data_document_type(merged_payload, logical_type)
  document_type_v2 = ComplyanceSDK::Models::LogicalDocTypeMapper.to_gets_document_type_v2(logical_type)
  push_to_unify_v2(source_name, source_version, document_type_v2, country, operation, mode, purpose, merged_payload, destinations)
end

.push_to_unify_request(request) ⇒ ComplyanceSDK::Models::UnifyResponse

Main API method for document processing (UnifyRequest object)

Parameters:

Returns:



272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
# File 'lib/complyance_sdk.rb', line 272

def push_to_unify_request(request)
  unless configured?
    raise ComplyanceSDK::Exceptions::ConfigurationError.new(
      "SDK must be configured before making API calls"
    )
  end

  # Convert hash to UnifyRequest if needed
  if request.is_a?(Hash)
    request = ComplyanceSDK::Models::UnifyRequest.from_h(request)
  end

  # Validate the request
  unless request.valid?
    raise ComplyanceSDK::Exceptions::ValidationError.new(
      "Invalid request: #{request.errors.join(', ')}",
      context: { errors: request.errors }
    )
  end

  # Make the API call with retry logic
  response_data = with_retry("push_to_unify", { request_id: request.[:request_id] }) do
    http_client.post("", request.to_h)
  end

  # Convert response to UnifyResponse object
  ComplyanceSDK::Models::UnifyResponse.from_h(response_data)
end

.push_to_unify_v2(source_name, source_version, document_type_v2, country, operation, mode, purpose, payload, destinations = nil) ⇒ ComplyanceSDK::Models::UnifyResponse

Push to Unify API with GETS V2 document type

Parameters:

  • source_name (String)

    The source name

  • source_version (String)

    The source version

  • document_type_v2 (ComplyanceSDK::Models::GetsDocumentTypeV2)

    The V2 document type

  • country (Symbol)

    The country code

  • operation (Symbol)

    The operation type

  • mode (Symbol)

    The mode

  • purpose (Symbol)

    The purpose

  • payload (Hash)

    The business data payload

  • destinations (Array, nil) (defaults to: nil)

    Optional destinations

Returns:



457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
# File 'lib/complyance_sdk.rb', line 457

def push_to_unify_v2(source_name, source_version, document_type_v2, country, operation, mode, purpose, payload, destinations = nil)
  unless configured?
    raise ComplyanceSDK::Exceptions::ConfigurationError.new(
      "SDK must be configured before making API calls"
    )
  end

  # Process queued submissions first before handling new requests
  process_queued_submissions_first

  # Validate required parameters
  # Handle source_name and source_version based on purpose
  final_source_name = if purpose == :mapping
                        # For MAPPING purpose, source_name and source_version are optional
                        source_name || ""
                      else
                        # For all other purposes, source_name is mandatory
                        if source_name.nil? || source_name.to_s.strip.empty?
                          raise ComplyanceSDK::Exceptions::ValidationError.new(
                            "Source name is required",
                            context: { field: :source_name }
                          )
                        end
                        source_name
                      end

  final_source_version = if purpose == :mapping
                           # For MAPPING purpose, source_version is optional
                           source_version || ""
                         else
                           # For all other purposes, source_version is mandatory
                           if source_version.nil? || source_version.to_s.strip.empty?
                             raise ComplyanceSDK::Exceptions::ValidationError.new(
                               "Source version is required",
                               context: { field: :source_version }
                             )
                           end
                           source_version
                         end

  # Validate other required parameters
  validate_required_parameter(document_type_v2, :document_type_v2, "GETS V2 documentType is required")
  validate_required_parameter(country, :country, "Country is required")
  validate_required_parameter(operation, :operation, "Operation is required")
  validate_required_parameter(mode, :mode, "Mode is required")
  validate_required_parameter(purpose, :purpose, "Purpose is required")
  validate_required_parameter(payload, :payload, "Payload is required")

  normalized_document_type_v2 = normalize_and_validate_document_type_v2(document_type_v2)

  # Validate country restrictions for current environment
  validate_country_for_environment(country, configuration.environment)

  request_payload = payload.dup
  set_payload_document_type_v2(request_payload, normalized_document_type_v2)
  set_invoice_data_document_type_from_v2(request_payload, normalized_document_type_v2.base)

  # Create source reference with type from configuration
  source_type = find_source_type(final_source_name, final_source_version)
  source_ref = ComplyanceSDK::Models::SourceRef.new(final_source_name, final_source_version, source_type)

  # Auto-generate destinations if none provided and auto-generation is enabled
  final_destinations = destinations || (configuration.auto_generate_tax_destination? ? 
                                      generate_default_destinations(country, normalized_document_type_v2.base) : [])

  # Build and send request using the resolved base document type
  push_to_unify_internal_with_document_type(
    source_ref,
    resolve_base_document_type_from_v2(normalized_document_type_v2.base),
    normalized_document_type_v2.base,
    country,
    operation,
    mode,
    purpose,
    request_payload,
    final_destinations,
    normalized_document_type_v2
  )
end

.push_to_unify_with_document_type(source_name, source_version, document_type, country, operation, mode, purpose, payload, destinations = nil) ⇒ Object



537
538
539
540
541
542
543
544
545
546
547
548
549
# File 'lib/complyance_sdk.rb', line 537

def push_to_unify_with_document_type(source_name, source_version, document_type, country, operation, mode, purpose, payload, destinations = nil)
  push_to_unify_v2(
    source_name,
    source_version,
    document_type,
    country,
    operation,
    mode,
    purpose,
    payload,
    destinations
  )
end

.push_to_unify_with_source_ref(source_ref, logical_type, country, operation, mode, purpose, payload, destinations = nil) ⇒ ComplyanceSDK::Models::UnifyResponse

Push to Unify API with logical document types using SourceRef

Parameters:

  • source_ref (ComplyanceSDK::Models::SourceRef)

    The source reference

  • logical_type (Symbol)

    The logical document type

  • country (Symbol)

    The country code

  • operation (Symbol)

    The operation type

  • mode (Symbol)

    The mode

  • purpose (Symbol)

    The purpose

  • payload (Hash)

    The business data payload

  • destinations (Array, nil) (defaults to: nil)

    Optional destinations

Returns:



562
563
564
565
566
567
568
569
570
571
572
573
574
# File 'lib/complyance_sdk.rb', line 562

def push_to_unify_with_source_ref(source_ref, logical_type, country, operation, mode, purpose, payload, destinations = nil)
  push_to_unify_logical(
    source_ref.name,
    source_ref.version,
    logical_type,
    country,
    operation,
    mode,
    purpose,
    payload,
    destinations
  )
end

.queue_statusHash

Get queue status and statistics

Returns:

  • (Hash)

    Queue status information



621
622
623
624
625
626
627
# File 'lib/complyance_sdk.rb', line 621

def queue_status
  if queue_manager
    queue_manager.queue_status
  else
    { error: "Queue Manager is not initialized" }
  end
end

.queue_status_detailedObject



636
637
638
# File 'lib/complyance_sdk.rb', line 636

def queue_status_detailed
  detailed_queue_status
end

.resume_queue_processingObject



683
684
685
# File 'lib/complyance_sdk.rb', line 683

def resume_queue_processing
  queue_manager&.resume_processing
end

.retry_failed(queue_item_id) ⇒ Object



645
646
647
# File 'lib/complyance_sdk.rb', line 645

def retry_failed(queue_item_id)
  queue_manager&.retry_failed(queue_item_id) || false
end

.retry_failed_submissionsObject

Retry failed submissions



641
642
643
# File 'lib/complyance_sdk.rb', line 641

def retry_failed_submissions
  queue_manager&.retry_failed_submissions
end

.retry_manager(redis_config = {}) ⇒ ComplyanceSDK::Retry::RetryManager

Get the retry manager instance

Parameters:

  • redis_config (Hash) (defaults to: {})

    Optional Redis configuration

Returns:



81
82
83
# File 'lib/complyance_sdk.rb', line 81

def retry_manager(redis_config = {})
  @retry_manager ||= ComplyanceSDK::Retry::RetryManager.new(configuration, redis_config)
end

.submit_invoice(options = {}) ⇒ ComplyanceSDK::Models::UnifyResponse

Convenience method for submitting invoices

Parameters:

  • options (Hash) (defaults to: {})

    Invoice submission options

Options Hash (options):

  • :country (String)

    Country code

  • :payload (Hash)

    Invoice payload

  • :source (ComplyanceSDK::Models::Source)

    Source information

  • :document_type (Symbol)

    Document type (default: :tax_invoice)

  • :purpose (Symbol)

    Purpose (default: :invoicing)

Returns:



310
311
312
313
314
315
316
317
318
319
320
321
322
# File 'lib/complyance_sdk.rb', line 310

def submit_invoice(options = {})
  request = ComplyanceSDK::Models::UnifyRequest.new(
    source: options[:source] || default_source,
    document_type: options[:document_type] || :tax_invoice,
    country: options[:country],
    operation: :single,
    mode: :documents,
    purpose: options[:purpose] || :invoicing,
    payload: options[:payload]
  )

  push_to_unify(request)
end

.submit_invoice_logical(source_name, source_version, country, logical_type, payload) ⇒ ComplyanceSDK::Models::UnifyResponse

Convenience method to submit invoices with logical document types

Parameters:

  • source_name (String)

    The source name

  • source_version (String)

    The source version

  • country (Symbol)

    The country code

  • logical_type (Symbol)

    The logical document type

  • payload (Hash)

    The business data payload

Returns:



584
585
586
587
588
589
590
591
592
593
594
595
# File 'lib/complyance_sdk.rb', line 584

def submit_invoice_logical(source_name, source_version, country, logical_type, payload)
  push_to_unify_logical(
    source_name,
    source_version,
    logical_type,
    country,
    :single,
    :documents,
    :invoicing,
    payload
  )
end

.verify_webhook_signature(payload, signature, secret, algorithm = "sha256") ⇒ Object



727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
# File 'lib/complyance_sdk.rb', line 727

def verify_webhook_signature(payload, signature, secret, algorithm = "sha256")
  normalized_algorithm = algorithm.to_s.downcase
  unless %w[sha256 sha512].include?(normalized_algorithm)
    raise ComplyanceSDK::Exceptions::ValidationError.new(
      "Unsupported webhook HMAC algorithm: #{algorithm}",
      context: { suggestion: "Use sha256 or sha512." }
    )
  end

  expected_signature = OpenSSL::HMAC.hexdigest(normalized_algorithm, secret.to_s, payload.to_s)
  unless secure_compare(expected_signature, signature.to_s.strip)
    raise ComplyanceSDK::Exceptions::ValidationError.new(
      "Webhook signature verification failed",
      context: {
        suggestion: "Ensure you use the raw request body and the correct webhook secret."
      }
    )
  end

  true
end

.with_retry(operation_name, context = {}) { ... } ⇒ Object

Execute an operation with retry logic

Parameters:

  • operation_name (String)

    Name of the operation

  • context (Hash) (defaults to: {})

    Context information

Yields:

  • The block to execute

Returns:

  • The result of the block



104
105
106
107
108
109
110
111
112
# File 'lib/complyance_sdk.rb', line 104

def with_retry(operation_name, context = {})
  unless configured?
    raise ComplyanceSDK::Exceptions::ConfigurationError.new(
      "SDK must be configured before using retry functionality"
    )
  end

  retry_manager.execute(operation_name, context) { yield }
end