8 Commits

7 changed files with 33 additions and 22 deletions

View File

@@ -7,6 +7,7 @@ gem 'nhtsa_vin'
gem 'will_paginate' gem 'will_paginate'
gem 'rails-jquery-autocomplete' gem 'rails-jquery-autocomplete'
gem 'jquery-ui-rails' gem 'jquery-ui-rails'
gem 'rexml'
group :assets do group :assets do
gem 'coffee-rails' gem 'coffee-rails'

View File

@@ -1,6 +1,6 @@
#The MIT License (MIT) #The MIT License (MIT)
# #
#Copyright (c) 2024 rick barrette #Copyright (c) 2016 - 2025 rick barrette
# #
#Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: #Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
# #
@@ -25,8 +25,8 @@ class QboController < ApplicationController
# Called when the user requests that Redmine to connect to QBO # Called when the user requests that Redmine to connect to QBO
# #
def authenticate def authenticate
redirect_uri = "https://" + Setting.host_name + qbo_oauth_callback_path redirect_uri = "#{Setting.protocol}://#{Setting.host_name + qbo_oauth_callback_path}"
logger.info "redirect_uri: " + redirect_uri logger.info "redirect_uri: #{redirect_uri}"
oauth2_client = Qbo.construct_oauth2_client oauth2_client = Qbo.construct_oauth2_client
grant_url = oauth2_client.auth_code.authorize_url(redirect_uri: redirect_uri, response_type: "code", state: SecureRandom.hex(12), scope: "com.intuit.quickbooks.accounting") grant_url = oauth2_client.auth_code.authorize_url(redirect_uri: redirect_uri, response_type: "code", state: SecureRandom.hex(12), scope: "com.intuit.quickbooks.accounting")
redirect_to grant_url redirect_to grant_url
@@ -39,7 +39,7 @@ class QboController < ApplicationController
if params[:state].present? if params[:state].present?
oauth2_client = Qbo.construct_oauth2_client oauth2_client = Qbo.construct_oauth2_client
# use the state value to retrieve from your backend any information you need to identify the customer in your system # use the state value to retrieve from your backend any information you need to identify the customer in your system
redirect_uri = "https://" + Setting.host_name + qbo_oauth_callback_path redirect_uri = "#{Setting.protocol}://#{Setting.host_name + qbo_oauth_callback_path}"
if resp = oauth2_client.auth_code.get_token(params[:code], redirect_uri: redirect_uri) if resp = oauth2_client.auth_code.get_token(params[:code], redirect_uri: redirect_uri)
# Remove the last authentication information # Remove the last authentication information
@@ -51,9 +51,9 @@ class QboController < ApplicationController
qbo.refresh_token! qbo.refresh_token!
if qbo.save! if qbo.save!
redirect_to qbo_sync_path, :flash => { :notice => "Successfully connected to Quickbooks" } redirect_to qbo_sync_path, :flash => { :notice => I18n.t(:label_connected) }
else else
redirect_to plugin_settings_path(:redmine_qbo), :flash => { :error => "Error" } redirect_to plugin_settings_path(:redmine_qbo), :flash => { :error => I18n.t(:label_error) }
end end
end end
@@ -65,9 +65,9 @@ class QboController < ApplicationController
i = Issue.find_by_id params[:id] i = Issue.find_by_id params[:id]
if i.customer if i.customer
i.bill_time i.bill_time
redirect_to i, :flash => { :notice => "Successfully Billed #{i.customer.name}" } redirect_to i, :flash => { :notice => I18n.t(:label_billed_success) + i.customer.name }
else else
redirect_to i, :flash => { :error => "Cannot bill without a customer assigned" } redirect_to i, :flash => { :error => I18n.t(:label_billing_error) }
end end
end end
@@ -152,6 +152,6 @@ class QboController < ApplicationController
ActiveRecord::Base.connection.close ActiveRecord::Base.connection.close
end end
redirect_to :home, :flash => { :notice => "Syncing Quickbooks" } redirect_to :home, :flash => { :notice => I18n.t(:label_syncing) }
end end
end end

View File

@@ -1,6 +1,6 @@
#The MIT License (MIT) #The MIT License (MIT)
# #
#Copyright (c) 2023 rick barrette #Copyright (c) 2016 - 2025 rick barrette
# #
#Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: #Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
# #
@@ -11,9 +11,6 @@
module QuickbooksOauth module QuickbooksOauth
extend ActiveSupport::Concern extend ActiveSupport::Concern
OAUTH_CONSUMER_KEY = Setting.plugin_redmine_qbo['settingsOAuthConsumerKey']
OAUTH_CONSUMER_SECRET = Setting.plugin_redmine_qbo['settingsOAuthConsumerSecret']
#== Instance Methods #== Instance Methods
def perform_authenticated_request(&block) def perform_authenticated_request(&block)
@@ -71,12 +68,20 @@ module QuickbooksOauth
module ClassMethods module ClassMethods
def construct_oauth2_client def construct_oauth2_client
oauth_consumer_key = Setting.plugin_redmine_qbo['settingsOAuthConsumerKey']
oauth_consumer_secret = Setting.plugin_redmine_qbo['settingsOAuthConsumerSecret']
# Are we are playing in the sandbox?
Quickbooks.sandbox_mode = Setting.plugin_redmine_qbo['sandbox'] ? true : false
logger.info "Sandbox mode: #{Quickbooks.sandbox_mode}"
options = { options = {
site: "https://appcenter.intuit.com/connect/oauth2", site: "https://appcenter.intuit.com/connect/oauth2",
authorize_url: "https://appcenter.intuit.com/connect/oauth2", authorize_url: "https://appcenter.intuit.com/connect/oauth2",
token_url: "https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer" token_url: "https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer"
} }
OAuth2::Client.new(OAUTH_CONSUMER_KEY, OAUTH_CONSUMER_SECRET, options) OAuth2::Client.new(oauth_consumer_key, oauth_consumer_secret, options)
end end
end end

View File

@@ -1,6 +1,6 @@
#The MIT License (MIT) #The MIT License (MIT)
# #
#Copyright (c) 2024 rick barrette #Copyright (c) 2016 - 2025 rick barrette
# #
#Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: #Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
# #
@@ -11,7 +11,6 @@
class Customer < ActiveRecord::Base class Customer < ActiveRecord::Base
has_many :issues has_many :issues
has_many :purchases
has_many :invoices has_many :invoices
has_many :estimates has_many :estimates
has_many :vehicles has_many :vehicles

View File

@@ -57,6 +57,13 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
</td> </td>
</tr> </tr>
<tr>
<th><%=t(:label_sandbox)%></th>
<td>
<%= check_box_tag 'settings[sandbox]', @settings['sandbox'], @settings['sandbox'] %>
</td>
</tr>
<tr> <tr>
<th><%=t(:label_oauth_expires)%></th> <th><%=t(:label_oauth_expires)%></th>
<td><%= if Qbo.exists? then Qbo.first.oauth2_access_token_expires_at end %> <td><%= if Qbo.exists? then Qbo.first.oauth2_access_token_expires_at end %>

View File

@@ -92,3 +92,5 @@ en:
label_appointment: "Add Appointment" label_appointment: "Add Appointment"
label_actions: "Actions" label_actions: "Actions"
label_create_estimate: "Create Estimate" label_create_estimate: "Create Estimate"
label_syncing: "Syncing Quickbooks"
label_sandbox: "Sandbox"

View File

@@ -1,6 +1,6 @@
#The MIT License (MIT) #The MIT License (MIT)
# #
#Copyright (c) 2023 rick barrette #Copyright (c) 2016-2025 rick barrette
# #
#Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: #Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
# #
@@ -22,11 +22,11 @@ Redmine::Plugin.register :redmine_qbo do
name 'Redmine Quickbooks Online plugin' name 'Redmine Quickbooks Online plugin'
author 'Rick Barrette' author 'Rick Barrette'
description 'This is a plugin for Redmine to intergrate with Quickbooks Online to allow for seamless intergration CRM and invoicing of completed issues' description 'This is a plugin for Redmine to intergrate with Quickbooks Online to allow for seamless intergration CRM and invoicing of completed issues'
version '2.1.1' version '2025.7.1'
url 'https://github.com/rickbarrette/redmine_qbo' url 'https://github.com/rickbarrette/redmine_qbo'
author_url 'https://barrettefabrication.com' author_url 'https://barrettefabrication.com'
settings :default => {'empty' => true}, :partial => 'qbo/settings' settings :default => {'empty' => true}, :partial => 'qbo/settings'
requires_redmine :version_or_higher => '5.1.0' requires_redmine :version_or_higher => '6.0.0'
# Add safe attributes for core models # Add safe attributes for core models
Issue.safe_attributes 'customer_id' Issue.safe_attributes 'customer_id'
@@ -39,9 +39,6 @@ Redmine::Plugin.register :redmine_qbo do
Project.safe_attributes 'customer_id' Project.safe_attributes 'customer_id'
Project.safe_attributes 'vehicle_id' Project.safe_attributes 'vehicle_id'
# We are playing in the sandbox
#Quickbooks.sandbox_mode = true
# set per_page globally # set per_page globally
WillPaginate.per_page = 20 WillPaginate.per_page = 20