mirror of
https://github.com/rickbarrette/redmine_qbo.git
synced 2026-04-02 08:21:57 -04:00
Refactored QBO service calls
This commit is contained in:
@@ -16,11 +16,9 @@ class QboSyncJob < ApplicationJob
|
||||
def perform(full_sync: false, id: nil, entity: nil, doc_number: nil)
|
||||
raise "An entity to sync is required" unless entity
|
||||
@entity = entity
|
||||
qbo = QboConnectionService.current!
|
||||
raise "No QBO configuration found" unless qbo
|
||||
|
||||
log "Starting #{full_sync ? 'full' : 'incremental'} sync for #{entity} ##{id || doc_number || 'all'}..."
|
||||
service = "#{entity}SyncService".constantize.new(qbo: qbo)
|
||||
service = "#{entity}SyncService".constantize.new
|
||||
|
||||
if id.present?
|
||||
service.sync_by_id(id)
|
||||
|
||||
@@ -98,15 +98,13 @@ class QboBaseModel < ActiveRecord::Base
|
||||
# Fetches the entity's details from QuickBooks Online.
|
||||
def fetch_details
|
||||
log "Fetching details for #{model_name.name} ##{id} from QBO..."
|
||||
qbo = QboConnectionService.current!
|
||||
service_class.new(qbo: qbo, local: self).pull()
|
||||
service_class.new(local: self).pull()
|
||||
end
|
||||
|
||||
# Pushs the entity's details from QuickBooks Online.
|
||||
def push_to_qbo
|
||||
log "Starting push for #{model_name.name} ##{id}..."
|
||||
qbo = QboConnectionService.current!
|
||||
reslut = service_class.new(qbo: qbo, local: self).push
|
||||
reslut = service_class.new(local: self).push
|
||||
Rails.cache.delete(details_cache_key)
|
||||
return reslut
|
||||
end
|
||||
|
||||
@@ -13,7 +13,7 @@ class EstimateSyncService < SyncServiceBase
|
||||
# sync only one estimate
|
||||
def sync_by_doc_number(number)
|
||||
log "Syncing estimate by doc number #{number}"
|
||||
with_qbo_service do |service|
|
||||
QboConnectionService.with_qbo_service(entity: @entity) do |service|
|
||||
persist(service.find_by( :doc_number, number).first)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -17,20 +17,11 @@ class InvoicePushService
|
||||
# Push invoice changes to QBO if the invoice is linked to any issues with custom field changes that need to be synced
|
||||
def push
|
||||
return if @invoice.qbo_sync_locked?
|
||||
|
||||
log "Pushing invoice ##{@invoice.id} to QBO due to linked issue custom field changes"
|
||||
|
||||
@invoice.update_column(:qbo_sync_locked, true)
|
||||
|
||||
qbo = QboConnectionService.current!
|
||||
|
||||
qbo.perform_authenticated_request do |access_token|
|
||||
service = Quickbooks::Service::Invoice.new( company_id: qbo.realm_id, access_token: access_token)
|
||||
|
||||
remote = QboConnectionService.with_qbo_service(entity: Invoice) do |service|
|
||||
remote = service.fetch_by_id(@invoice.id)
|
||||
|
||||
# modify remote object here if needed
|
||||
|
||||
service.update(remote)
|
||||
end
|
||||
rescue => e
|
||||
|
||||
@@ -15,8 +15,6 @@ class PdfService
|
||||
def initialize(entity: entity)
|
||||
raise "An entity to sync is required" unless entity
|
||||
@entity = entity
|
||||
@qbo = QboConnectionService.current!
|
||||
raise "No QBO configuration found" unless @qbo
|
||||
end
|
||||
|
||||
# Fetches the PDF for the given entity IDs. If multiple IDs are provided, their PDFs are combined into a single document.
|
||||
|
||||
@@ -10,6 +10,11 @@
|
||||
|
||||
class QboConnectionService
|
||||
|
||||
# Returns the current QBO connection record. Raises an error if no connection exists.
|
||||
def self.current!
|
||||
Qbo.first || raise("QBO not connected")
|
||||
end
|
||||
|
||||
# Replaces the existing QBO connection with new credentials. Deletes all existing records and creates a new one with the provided token, refresh token, and realm ID. Refreshes the token immediately after creation.
|
||||
def self.replace!(token:, refresh_token:, realm_id:)
|
||||
Qbo.transaction do
|
||||
@@ -24,9 +29,14 @@ class QboConnectionService
|
||||
end
|
||||
end
|
||||
|
||||
# Returns the current QBO connection record. Raises an error if no connection exists.
|
||||
def self.current!
|
||||
Qbo.first || raise("QBO not connected")
|
||||
# Performs authenticaed requests with QBO service
|
||||
def self.with_qbo_service(entity: nil)
|
||||
qbo = current!
|
||||
raise "An entity to sync is required" unless entity
|
||||
service_class ||= "Quickbooks::Service::#{entity}".constantize
|
||||
qbo.perform_authenticated_request do |access_token|
|
||||
service = service_class.new( company_id: qbo.realm_id, access_token: access_token )
|
||||
yield service
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -13,11 +13,9 @@ class ServiceBase
|
||||
# Subclasses should Initializes the service with a QBO client and a local record.
|
||||
# The QBO client is used to communicate with QuickBooks Online, while the local record contains the data that needs to be pushed to QBO.
|
||||
# If no local is provided, the service will not perform any operations.
|
||||
def initialize(qbo:, local: nil)
|
||||
def initialize(local: nil)
|
||||
@entity = local.class.name
|
||||
raise "No QBO configuration found" unless qbo
|
||||
raise "#{@entity} record is required for push operation" unless local
|
||||
@qbo = qbo
|
||||
@local = local
|
||||
end
|
||||
|
||||
@@ -31,7 +29,7 @@ class ServiceBase
|
||||
return build_qbo_remote unless @local.present?
|
||||
return build_qbo_remote unless @local.id
|
||||
log "Fetching details for #{@entity} ##{@local.id} from QBO..."
|
||||
with_qbo_service do |service|
|
||||
QboConnectionService.with_qbo_service(entity: @entity) do |service|
|
||||
service.fetch_by_id(@local.id)
|
||||
end
|
||||
rescue => e
|
||||
@@ -45,7 +43,7 @@ class ServiceBase
|
||||
# If the push is successful, it returns the remote record; otherwise, it logs the error and returns false.
|
||||
def push
|
||||
log "Pushing #{@entity} ##{@local.id} to QBO..."
|
||||
remote = with_qbo_service do |service|
|
||||
remote = QboConnectionService.with_qbo_service(entity: @entity) do |service|
|
||||
if @local.id.present?
|
||||
log "Updating #{@entity}"
|
||||
service.update(@local.details)
|
||||
@@ -61,22 +59,9 @@ class ServiceBase
|
||||
|
||||
private
|
||||
|
||||
# Performs authenticaed requests with QBO service
|
||||
def with_qbo_service
|
||||
@qbo.perform_authenticated_request do |access_token|
|
||||
service = service_class.new( company_id: @qbo.realm_id, access_token: access_token )
|
||||
yield service
|
||||
end
|
||||
end
|
||||
|
||||
# Log messages with the entity type for better traceability
|
||||
def log(msg)
|
||||
Rails.logger.info "[#{@entity}Service] #{msg}"
|
||||
end
|
||||
|
||||
# Dynamically get the Quickbooks Service Class
|
||||
def service_class
|
||||
@service_class ||= "Quickbooks::Service::#{@entity}".constantize
|
||||
end
|
||||
|
||||
end
|
||||
@@ -12,9 +12,7 @@ class SyncServiceBase
|
||||
PAGE_SIZE = 1000
|
||||
|
||||
# Subclasses should initialize with a QBO client instance
|
||||
def initialize(qbo:)
|
||||
raise "No QBO configuration found" unless qbo
|
||||
@qbo = qbo
|
||||
def initialize()
|
||||
@entity = self.class.model_class
|
||||
@page_size = self.class.page_size
|
||||
end
|
||||
@@ -32,7 +30,7 @@ class SyncServiceBase
|
||||
# Sync all entities, or only those updated since the last sync
|
||||
def sync(full_sync: false)
|
||||
log "Starting #{full_sync ? 'full' : 'incremental'} #{@entity.name} sync with page size of: #{@page_size}"
|
||||
with_qbo_service do |service|
|
||||
QboConnectionService.with_qbo_service(entity: @entity) do |service|
|
||||
query = build_query(full_sync)
|
||||
service.query_in_batches(query, per_page: @page_size) do |batch|
|
||||
entries = Array(batch)
|
||||
@@ -49,7 +47,7 @@ class SyncServiceBase
|
||||
# Sync a single entity by its QBO ID (webhook usage)
|
||||
def sync_by_id(id)
|
||||
log "Syncing #{@entity.name} with ID #{id}"
|
||||
with_qbo_service do |service|
|
||||
QboConnectionService.with_qbo_service(entity: @entity) do |service|
|
||||
remote = service.fetch_by_id(id)
|
||||
persist(remote)
|
||||
end
|
||||
@@ -240,17 +238,4 @@ class SyncServiceBase
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Dynamically get the Quickbooks Service Class
|
||||
def service_class
|
||||
@service_class ||= "Quickbooks::Service::#{@entity}".constantize
|
||||
end
|
||||
|
||||
# Performs authenticaed requests with QBO service
|
||||
def with_qbo_service
|
||||
@qbo.perform_authenticated_request do |access_token|
|
||||
service = service_class.new( company_id: @qbo.realm_id, access_token: access_token )
|
||||
yield service
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user