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/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, PurchaseInvoice, Queue, Retry Classes: Railtie

Constant Summary collapse

VERSION =
"3.0.7"

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.configurationObject

Returns the value of attribute configuration.



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

def configuration
  @configuration
end

Class Method Details

.cleanup_duplicate_filesObject

Clean up duplicate files across queue directories



652
653
654
655
656
657
658
# File 'lib/complyance_sdk.rb', line 652

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



638
639
640
# File 'lib/complyance_sdk.rb', line 638

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)



643
644
645
646
647
648
649
# File 'lib/complyance_sdk.rb', line 643

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:



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

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:



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

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:



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

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



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

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:



318
319
320
321
322
323
324
325
326
327
328
329
330
# File 'lib/complyance_sdk.rb', line 318

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:



591
592
593
594
595
596
597
598
599
600
601
602
# File 'lib/complyance_sdk.rb', line 591

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



618
619
620
# File 'lib/complyance_sdk.rb', line 618

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

.drain_queue(timeout_seconds = 30) ⇒ Object



673
674
675
# File 'lib/complyance_sdk.rb', line 673

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



336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
# File 'lib/complyance_sdk.rb', line 336

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



688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
# File 'lib/complyance_sdk.rb', line 688

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).



369
370
371
# File 'lib/complyance_sdk.rb', line 369

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:



360
361
362
363
364
365
366
# File 'lib/complyance_sdk.rb', line 360

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



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

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

.pause_queue_processingObject



665
666
667
# File 'lib/complyance_sdk.rb', line 665

def pause_queue_processing
  queue_manager&.pause_processing
end

.process_pending_submissionsObject

Process pending submissions now



661
662
663
# File 'lib/complyance_sdk.rb', line 661

def process_pending_submissions
  queue_manager&.process_pending_submissions_now
end

.process_queued_submissions_firstObject

Process queued submissions before handling new requests



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

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:



112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/complyance_sdk.rb', line 112

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



381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
# File 'lib/complyance_sdk.rb', line 381

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:



137
138
139
140
141
142
143
144
145
146
147
148
149
150
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
# File 'lib/complyance_sdk.rb', line 137

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:



196
197
198
199
200
201
202
203
204
205
206
207
208
209
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
# File 'lib/complyance_sdk.rb', line 196

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:



422
423
424
425
426
427
428
429
# File 'lib/complyance_sdk.rb', line 422

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:



258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
# File 'lib/complyance_sdk.rb', line 258

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:



443
444
445
446
447
448
449
450
451
452
453
454
455
456
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
# File 'lib/complyance_sdk.rb', line 443

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



523
524
525
526
527
528
529
530
531
532
533
534
535
# File 'lib/complyance_sdk.rb', line 523

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:



548
549
550
551
552
553
554
555
556
557
558
559
560
# File 'lib/complyance_sdk.rb', line 548

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



607
608
609
610
611
612
613
# File 'lib/complyance_sdk.rb', line 607

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

.queue_status_detailedObject



622
623
624
# File 'lib/complyance_sdk.rb', line 622

def queue_status_detailed
  detailed_queue_status
end

.resume_queue_processingObject



669
670
671
# File 'lib/complyance_sdk.rb', line 669

def resume_queue_processing
  queue_manager&.resume_processing
end

.retry_failed(queue_item_id) ⇒ Object



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

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

.retry_failed_submissionsObject

Retry failed submissions



627
628
629
# File 'lib/complyance_sdk.rb', line 627

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:



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

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:



296
297
298
299
300
301
302
303
304
305
306
307
308
# File 'lib/complyance_sdk.rb', line 296

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:



570
571
572
573
574
575
576
577
578
579
580
581
# File 'lib/complyance_sdk.rb', line 570

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



713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
# File 'lib/complyance_sdk.rb', line 713

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



90
91
92
93
94
95
96
97
98
# File 'lib/complyance_sdk.rb', line 90

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