Class: Effective::QbApi

Inherits:
Object
  • Object
show all
Defined in:
app/models/effective/qb_api.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(realm:) ⇒ QbApi

Returns a new instance of QbApi.



8
9
10
11
# File 'app/models/effective/qb_api.rb', line 8

def initialize(realm:)
  raise('expected an Effective::QbRealm') unless realm.kind_of?(Effective::QbRealm)
  @realm = realm
end

Instance Attribute Details

#realmObject

Returns the value of attribute realm.



6
7
8
# File 'app/models/effective/qb_api.rb', line 6

def realm
  @realm
end

Instance Method Details

#accountsObject



57
58
59
# File 'app/models/effective/qb_api.rb', line 57

def accounts
  with_service('Account') { |service| service.all }
end

#accounts_collectionObject

Only accounts we can use for the Deposit to Account setting



62
63
64
65
66
67
68
# File 'app/models/effective/qb_api.rb', line 62

def accounts_collection
  accounts
    .select { || ['Bank', 'Other Current Asset'].include?(.) }
    .sort_by { || [., .name] }
    .map { || [.name, .id, .] }
    .group_by(&:last)
end

#api_errorObject



44
45
46
47
48
49
50
# File 'app/models/effective/qb_api.rb', line 44

def api_error
  begin
    company_info.present?; nil
  rescue => e
    return e.message
  end
end

#app_urlObject



13
14
15
# File 'app/models/effective/qb_api.rb', line 13

def app_url
  Quickbooks.sandbox_mode ? 'https://app.sandbox.qbo.intuit.com/app' : 'https://app.qbo.intuit.com/app'
end

#build_address(address) ⇒ Object



30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'app/models/effective/qb_api.rb', line 30

def build_address(address)
  raise('Expected a Effective::Address') unless address.kind_of?(Effective::Address)

  Quickbooks::Model::PhysicalAddress.new(
    line1: address.address1,
    line2: address.address2,
    line3: address.try(:address3),
    city: address.city,
    country: address.country,
    country_sub_division_code: address.country_code,
    postal_code: address.postal_code
  )
end

#company_infoObject

Singular



53
54
55
# File 'app/models/effective/qb_api.rb', line 53

def company_info
  with_service('CompanyInfo') { |service| service.fetch_by_id(realm.realm_id) }
end

#create_customer(order:) ⇒ Object



131
132
133
134
135
136
137
138
139
140
141
142
# File 'app/models/effective/qb_api.rb', line 131

def create_customer(order:)
  raise('expected an Effective::Order') unless order.kind_of?(Effective::Order)

  with_service('Customer') do |service|
    customer = Quickbooks::Model::Customer.new(
      primary_email_address: Quickbooks::Model::EmailAddress.new(order.email),
      display_name: scrub(order.qb_online_customer_display_name)
    )

    service.create(customer)
  end
end

#create_sales_receipt(sales_receipt:) ⇒ Object



148
149
150
# File 'app/models/effective/qb_api.rb', line 148

def create_sales_receipt(sales_receipt:)
  with_service('SalesReceipt') { |service| service.create(sales_receipt) }
end

#customer_url(obj) ⇒ Object



21
22
23
# File 'app/models/effective/qb_api.rb', line 21

def customer_url(obj)
  "#{app_url}/customerdetail?nameId=#{obj.try(:customer_id) || obj.try(:id) || obj}"
end

#delete_customer(customer:) ⇒ Object



144
145
146
# File 'app/models/effective/qb_api.rb', line 144

def delete_customer(customer:)
  with_service('Customer') { |service| service.delete(customer) }
end

#find_customer(order:) ⇒ Object



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'app/models/effective/qb_api.rb', line 104

def find_customer(order:)
  raise('expected an Effective::Order') unless order.kind_of?(Effective::Order)

  with_service('Customer') do |service|
    util = Quickbooks::Util::QueryBuilder.new

    # Find by display name
    customer = service.find_by(:display_name, scrub(order.qb_online_customer_display_name))&.first

    # Find by email
    customer ||= if order.email.present?
      email = util.clause("PrimaryEmailAddr", "LIKE", order.email)
      service.query("SELECT * FROM Customer WHERE #{email}")&.first
    end

    # Find by first name and last name
    customer ||= if order.billing_first_name.present? && order.billing_last_name.present?
      first_name = util.clause("GivenName", "LIKE", order.billing_first_name)
      last_name = util.clause("FamilyName", "LIKE", order.billing_last_name)
      service.query("SELECT * FROM Customer WHERE #{first_name} AND #{last_name}")&.first
    end

    customer
  end
end

#find_or_create_customer(order:) ⇒ Object



100
101
102
# File 'app/models/effective/qb_api.rb', line 100

def find_or_create_customer(order:)
  find_customer(order: order) || create_customer(order: order)
end

#find_sales_receipt(id:) ⇒ Object



152
153
154
# File 'app/models/effective/qb_api.rb', line 152

def find_sales_receipt(id:)
  with_service('SalesReceipt') { |service| service.find_by(:id, id) }
end

#item_html(item) ⇒ Object



82
83
84
85
86
87
88
89
90
# File 'app/models/effective/qb_api.rb', line 82

def item_html(item)
  details = [
    ("##{item.id}"),
    (item.sku if item.sku.present?),
    (item.description if item.description.present?)
  ].compact.join(', ')

  "<span>#{item.name}</span> <small>(#{details})</small>"
end

#itemsObject



70
71
72
# File 'app/models/effective/qb_api.rb', line 70

def items
  with_service('Item') { |service| service.all }
end

#items_collectionObject



74
75
76
77
78
79
80
# File 'app/models/effective/qb_api.rb', line 74

def items_collection
  items
    .reject { |item| item.type == 'Category' }
    .sort_by { |item| [item.type, item.name] }
    .map { |item| [item.name, item.id, {'data-html': item_html(item)}, item.type] }
    .group_by(&:last)
end

#payment_methodsObject



92
93
94
# File 'app/models/effective/qb_api.rb', line 92

def payment_methods
  with_service('PaymentMethod') { |service| service.all }
end

#payment_methods_collectionObject



96
97
98
# File 'app/models/effective/qb_api.rb', line 96

def payment_methods_collection
  payment_methods.sort_by(&:name).map { |payment_method| [payment_method.name, payment_method.id] }
end

#price_to_amount(price) ⇒ Object



25
26
27
28
# File 'app/models/effective/qb_api.rb', line 25

def price_to_amount(price)
  raise('Expected an Integer price') unless price.kind_of?(Integer)
  (price / 100.0).round(2)
end

#sales_receipt_url(obj) ⇒ Object



17
18
19
# File 'app/models/effective/qb_api.rb', line 17

def sales_receipt_url(obj)
  "#{app_url}/salesreceipt?txnId=#{obj.try(:sales_receipt_id) || obj.try(:id) || obj}"
end

#tax_codesObject



156
157
158
# File 'app/models/effective/qb_api.rb', line 156

def tax_codes
  with_service('TaxCode') { |service| service.all }
end

#tax_ratesObject



160
161
162
# File 'app/models/effective/qb_api.rb', line 160

def tax_rates
  with_service('TaxRate') { |service| service.all }
end

#taxes_collectionObject

Returns a Hash of BigDecimal.to_s String Tax Rate => TaxCode Object { ‘0.0’ => ‘Quickbooks::Model::TaxCode(Exempt)’, ‘5.0’ => ‘Quickbooks::Model::TaxCode(GST)’ }



166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# File 'app/models/effective/qb_api.rb', line 166

def taxes_collection
  rates = tax_rates()
  codes = tax_codes()

  # Find Exempt 0.0
  exempt = codes.find do |code|
    rate_id = code.sales_tax_rate_list.tax_rate_detail.first&.tax_rate_ref&.value
    rate = rates.find { |rate| rate.id == rate_id } if rate_id

    code.name.downcase.include?('exempt') && rate && rate.rate_value == 0.0
  end

  exempt = [['0.0', exempt]] if exempt.present?

  # Find The rest
  tax_codes = codes.select(&:active?).map do |code|
    rate_id = code.sales_tax_rate_list.tax_rate_detail.first&.tax_rate_ref&.value
    rate = rates.find { |rate| rate.id == rate_id } if rate_id

    [rate.rate_value.to_s, code] if rate && (exempt.blank? || rate.rate_value.to_f > 0.0)
  end

  (Array(exempt) + tax_codes.uniq { |key, _| key }.compact).to_h
end

#with_service(name, &block) ⇒ Object



191
192
193
194
195
196
197
198
# File 'app/models/effective/qb_api.rb', line 191

def with_service(name, &block)
  klass = "Quickbooks::Service::#{name}".constantize

  with_authenticated_request do |access_token|
    service = klass.new(company_id: realm.realm_id, access_token: access_token)
    yield(service)
  end
end