141 Commits
0.7.0 ... 1.0.0

Author SHA1 Message Date
d6aebfcb99 Moved strings to Ruby I18n en.yml 2022-02-19 20:46:39 -05:00
2085eb7869 Add gem dependancy faraday_middleware 1.2.0 to fix NoMethodError: undefined method `dependency' for Gzip:Class 2022-02-18 22:42:20 -05:00
c101a86f02 Open Estimate PDF in new windows 2022-02-17 09:19:32 -05:00
2d32769a59 Error not fatal 2022-02-13 13:19:04 -05:00
a2f755388e Fixed merge error 2022-02-13 12:34:03 -05:00
8a8f1af2bd Updated Copyright 2022 2022-02-13 11:57:43 -05:00
4582b8c5b9 Added estimate search in side bar 2022-02-13 10:03:43 -05:00
f66fbf6656 specified the rails version in migrations 2022-02-12 16:14:36 -05:00
41d49ccce5 Setting.host_name for hooks not a hardcoded URL 2022-02-12 09:24:21 -05:00
c85f450742 Merge branch 'master' into redmine-4 2022-02-12 09:19:36 -05:00
e314dae10d Logging & exception handler for updating invoices 2022-02-12 09:12:11 -05:00
b1192a1912 Use host name from settings for auth & added exception handing in QboInvoice 2022-02-06 16:37:00 -05:00
7cc8a946fd Inital update for redmine 4.0+ compatibility 2022-02-01 20:53:20 -05:00
4b34852c72 Don't include open issues in closed issue list 2020-03-30 20:56:38 -04:00
5d7fc9dabd Don't include open issues in closed issue list 2020-03-28 20:39:04 -04:00
db61952e67 added notes to regaurding customer autocomplete field 2020-03-28 20:19:58 -04:00
016dca242c Added comments to clearify methods 2020-03-28 20:16:54 -04:00
983811af97 Added comments to clearify methods 2020-03-28 20:08:44 -04:00
d18a9726ac Added onchange event to customer_id 2020-03-28 19:56:42 -04:00
cdef838d3e comment out missing method call 2020-03-26 20:31:00 -04:00
7703d724e1 Update issues_save_hook_listener.rb
titleize all subjects
2020-03-26 20:22:07 -04:00
94b5efbd00 forgot a comma 2020-03-26 12:53:59 -04:00
f43020b864 Update issues_form_hook_listener.rb
Added onchange listener to customer form field
2020-03-26 12:50:32 -04:00
0d0f808305 Merge branch 'master' of github.com:rickbarrette/redmine_qbo 2020-01-24 13:55:15 -05:00
279e8b15e0 Added open/closed issue lists for customer/vehicles 2020-01-24 13:54:26 -05:00
099f729303 Update README.md 2020-01-06 08:52:36 -05:00
5150a31cdb Removed unused gems 2020-01-05 12:33:52 -05:00
b5d17dc862 Removed oauth1 database columns & updated settings 2020-01-05 12:21:36 -05:00
e6c5feb3f3 Remove uneeded columns from qbos table 2020-01-05 12:03:19 -05:00
5573e941c6 Cleaning up uneeded code 2020-01-05 11:58:27 -05:00
29dbca20e0 Update copyright 2020-01-05 11:44:02 -05:00
d6c114d52b Version 0.8.1 2020-01-05 09:20:23 -05:00
87b8daf283 Fixed expired token check 2020-01-05 09:17:50 -05:00
719abe20a6 Update qbo.rb 2020-01-05 01:22:27 -05:00
4a5b83265d Update qbo.rb 2020-01-05 01:20:23 -05:00
8d103d3fc6 Update qbo.rb 2020-01-05 01:12:48 -05:00
9310f207a3 Update qbo.rb 2020-01-05 01:08:42 -05:00
000b67b329 Added employee 2020-01-05 00:08:00 -05:00
ebee9395ba Update qbo_employee.rb 2020-01-05 00:06:45 -05:00
2cd6731f0c Update qbo_employee.rb 2020-01-05 00:05:25 -05:00
ebdbd25082 Update qbo.rb 2020-01-04 23:45:00 -05:00
18ada91fcd Update qbo.rb 2020-01-04 23:38:46 -05:00
1cf3926585 Update qbo.rb 2020-01-04 23:33:33 -05:00
e776deeece Update qbo.rb 2020-01-04 23:07:53 -05:00
8c2f30949a Update qbo.rb 2020-01-04 23:04:09 -05:00
015a989f72 Update qbo.rb 2020-01-04 22:57:53 -05:00
0d4d5a6136 Update qbo.rb 2020-01-04 22:52:01 -05:00
0364989fe1 Update qbo_controller.rb 2020-01-04 22:46:20 -05:00
fb47eaba0e Update qbo.rb 2020-01-04 22:45:31 -05:00
725d511be5 Update qbo.rb 2020-01-04 22:30:43 -05:00
fd85f296de Update 030_update_qbos_token.rb 2020-01-04 22:16:07 -05:00
9549bb8fe2 Update qbo.rb 2020-01-04 20:24:29 -05:00
6a1c8b0551 Update README.md 2020-01-04 16:09:03 -05:00
086632e804 Version 0.8.0 (OAuth 2.0) 2020-01-04 16:01:16 -05:00
d37ff922fc Update customer.rb 2020-01-04 15:51:04 -05:00
3483efa100 Oauth2 Upgrade 2020-01-04 15:41:15 -05:00
f65eea2820 Oauth2 Upgrade 2020-01-04 15:37:17 -05:00
a4111e0a11 oAuth2 Upgrade 2020-01-04 15:36:36 -05:00
ebe5373d82 Oauth2 Upgrade 2020-01-04 15:34:57 -05:00
5b8c7d42c5 Oauth2 Upgrade 2020-01-04 15:34:04 -05:00
b8fc57d583 Oauth2 Upgrade 2020-01-04 15:31:19 -05:00
7c42197cb1 Oauth2 Upgrade 2020-01-04 15:30:03 -05:00
cc0ffce892 Oauth2 Upgrade 2020-01-04 15:29:18 -05:00
0fd2abbec3 Oauth2 Upgrade 2020-01-04 15:28:43 -05:00
215b219a6d Oauth2 Upgrade 2020-01-04 15:28:04 -05:00
ea71542d81 Oauth2 Upgrade 2020-01-04 15:26:35 -05:00
5dbf486b50 Update qbo_controller.rb 2020-01-04 15:21:14 -05:00
b734125d6b Update qbo_controller.rb 2020-01-04 15:19:31 -05:00
06e6295c6e Update qbo.rb 2020-01-04 14:32:32 -05:00
fd383ad9d4 Update qbo.rb 2020-01-04 14:29:23 -05:00
4eb6c533f1 Update qbo.rb 2020-01-04 14:21:07 -05:00
5af7d73768 Update qbo_controller.rb 2020-01-04 14:18:42 -05:00
1d0ae34261 Update qbo.rb 2020-01-04 14:13:29 -05:00
21656b3e14 Update qbo.rb 2020-01-04 14:09:37 -05:00
131976cd71 Update issue_patch.rb 2020-01-04 14:08:48 -05:00
88c1b9c9a2 Update issue_patch.rb 2020-01-04 14:06:42 -05:00
5ea9aed3cb Update qbo.rb 2020-01-04 14:05:00 -05:00
41e10d9b0e Update qbo.rb 2020-01-04 13:59:09 -05:00
45859bef3e Update qbo.rb 2020-01-04 13:56:38 -05:00
f5c40738dc Update issue_patch.rb 2020-01-04 13:54:29 -05:00
bfa37ee634 Update issue_patch.rb 2020-01-04 13:51:31 -05:00
787b55f3d7 Update qbo.rb 2020-01-04 13:46:13 -05:00
61f882e98c Update qbo.rb 2020-01-04 13:45:00 -05:00
37db0d3d72 Update qbo.rb 2020-01-04 13:31:40 -05:00
4f2dec3069 Update qbo.rb 2020-01-04 13:29:36 -05:00
35a7c3cfeb Create 030_update_qbos_token.rb 2020-01-04 13:28:22 -05:00
cbbaf5a95c Update qbo.rb 2020-01-04 13:22:27 -05:00
647923e5e6 Update 029_update_qbos_types.rb 2020-01-04 13:19:21 -05:00
70ca4e9964 Create 029_update_qbos_types.rb 2020-01-04 13:17:15 -05:00
7fb40ad4a8 Update qbo_controller.rb 2020-01-04 13:09:09 -05:00
36083d23a0 Update qbo_controller.rb 2020-01-04 13:07:36 -05:00
2ec57f2bbf Update qbo_controller.rb 2020-01-04 13:06:23 -05:00
278708e566 Update qbo_controller.rb 2020-01-04 12:47:30 -05:00
23f2b92e8d Update qbo_controller.rb 2020-01-04 12:45:16 -05:00
5d92eeddfb Update qbo_controller.rb 2020-01-04 12:44:05 -05:00
384a8c033c Update qbo_controller.rb 2020-01-04 12:39:23 -05:00
32b12b60f9 Update qbo_controller.rb 2020-01-04 12:33:54 -05:00
93db447239 Update qbo_controller.rb 2020-01-04 12:29:54 -05:00
19a6180e15 Update qbo.rb 2020-01-04 12:26:04 -05:00
3408ee173c Update qbo.rb 2020-01-04 12:25:12 -05:00
b817e842dd Update qbo.rb 2020-01-04 12:23:59 -05:00
51c3b8338e Update qbo.rb 2020-01-04 12:23:05 -05:00
c6a3edfbc1 Update qbo_controller.rb 2020-01-04 12:21:45 -05:00
21d8d90465 Update qbo.rb 2020-01-04 12:21:24 -05:00
04c0fa57c6 Update qbo_controller.rb 2020-01-04 12:17:26 -05:00
f5ad761712 Update qbo_controller.rb 2020-01-04 12:14:54 -05:00
9b80485915 Update qbo.rb 2020-01-04 12:14:05 -05:00
87de865c00 oauth2 2020-01-04 11:51:25 -05:00
1ea27e8511 Only show error flash if errors are not empty 2019-11-12 12:50:44 -05:00
8f0ca00b09 Merge branch 'master' of github.com:rickbarrette/redmine_qbo 2019-11-12 12:45:20 -05:00
859a1d505b always show errors 2019-11-12 12:45:14 -05:00
cd109653a2 Merge branch 'master' of github.com:rickbarrette/redmine_qbo 2019-11-12 12:37:12 -05:00
cab723bbcd Removed styles & removed after find call 2019-11-12 12:36:25 -05:00
3dd712629b added local vin validation 2019-11-12 12:35:54 -05:00
cdf2603e12 Merge branch 'master' of github.com:rickbarrette/redmine_qbo 2019-11-12 12:16:30 -05:00
5df9d324bc Update vehicle.rb 2019-11-12 12:15:59 -05:00
f78c0338b4 Made decode_vin not private 2019-11-12 12:08:04 -05:00
fe6aa7908f Merge branch 'master' of github.com:rickbarrette/redmine_qbo 2019-11-12 11:51:54 -05:00
aa45338e36 Update vehicle.rb 2019-11-11 10:10:23 -05:00
213dca2621 Fixed redicect to :home 2019-07-08 11:30:53 -04:00
fee710d717 Rediect to vehicle if vin is already taken 2019-06-26 11:39:07 -04:00
65eac58f6c Update customer.rb 2019-06-25 12:48:35 -04:00
b4f5112fc3 Create 028_add_customers_mobile_phone_number.rb 2019-06-25 12:46:03 -04:00
fa5dcbf9a9 Fixed redirect to for new vehicles 2019-06-25 12:37:49 -04:00
e0aebb1c23 Update customer.rb 2019-06-25 11:59:08 -04:00
6d176acc2b Update customer.rb 2019-06-25 11:54:26 -04:00
9e9b29fef9 Update 027_add_customers_phone_number.rb 2019-06-25 11:53:40 -04:00
1af846537d Update customer.rb 2019-06-25 11:50:14 -04:00
d6c5daff49 Added phone number 2019-06-25 11:15:57 -04:00
61c76ad80a Create 027_add_customers_phone_number.rb 2019-06-25 10:59:34 -04:00
0d514790fd Moved issue.status.is_closed? check back into issue save hook 2019-03-26 12:15:03 -04:00
748d431d35 Removed controller_issues_edit_before_save hook 2019-03-26 12:11:54 -04:00
87b8d99c41 Working on issue.bill_time 2019-03-26 12:09:38 -04:00
a0da53b6cf Fixed formatting & removed search from heading 2018-10-15 21:10:41 -04:00
02d630c631 Fixed Invoice Link to be HTML safe 2018-10-15 21:07:36 -04:00
15b214c800 Moved html into partial view 2018-10-15 20:57:03 -04:00
1b5e185087 Added nil check 2018-10-15 19:42:41 -04:00
102309600e Merge branch 'master' of github.com:rickbarrette/redmine_qbo 2018-10-15 19:36:09 -04:00
6acc7db91b Changed Customer search to shown on all pages 2018-10-15 19:34:51 -04:00
02898883a8 Update line_item.rb 2018-10-14 23:35:13 -04:00
ce02b70bc3 Update line_items_controler.rb 2018-10-14 23:34:17 -04:00
91 changed files with 764 additions and 564 deletions

View File

@@ -1,15 +1,13 @@
source 'https://rubygems.org'
gem 'quickbooks-ruby'
gem 'quickbooks-ruby-base'
gem 'oauth-plugin'
gem 'oauth'
gem 'oauth2'
gem 'roxml'
gem 'nhtsa_vin'
gem 'will_paginate'
gem 'rails-jquery-autocomplete'
gem 'jquery-rails', '~> 3.1.4'
gem 'jquery-ui-rails'
gem 'faraday_middleware', '1.2.0'
group :assets do
gem 'coffee-rails'

View File

@@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2018 Rick Barrette
Copyright (c) 2022 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

View File

@@ -4,9 +4,11 @@ A plugin for Redmine to connect to Quickbooks Online
The goal of this project is to allow Redmine to connect with Quickbooks Online to create `Time Activity Entries` for completed work when an Issue is closed.
`Note: Although the core functionality is complete, this project is still under heavy development. I am still working on refining everthing and adding other features. Tags should be stable`
#### Disclaimer
`Note: I am currently using this in a live production enviroment with no issues`
Note: Although the core functionality is complete, this project is still under heavy development. I am still working on refining everthing and adding other features. Tags should be stable
Also worth metioning I am currently using this in a live production enviroment with no issues
#### Features
* Issues can be assigned to a `Customer` via drop down in the edit Issue form
@@ -77,7 +79,7 @@ Note: After the inital synchronization, this plugin will recieve push notificati
The MIT License (MIT)
Copyright (c) 2017 rick barrette
Copyright (c) 2020 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:

View File

@@ -1,6 +1,6 @@
#The MIT License (MIT)
#
#Copyright (c) 2017 rick barrette
#Copyright (c) 2022 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:
#
@@ -11,7 +11,7 @@
# This controller class will handle map management
class CustomersController < ApplicationController
unloadable
include AuthHelper
helper :issues
helper :journals
@@ -26,27 +26,37 @@ class CustomersController < ApplicationController
helper :sort
include SortHelper
helper :timelog
before_filter :add_customer, :only => :new
before_filter :view_customer, :except => :new
skip_before_filter :verify_authenticity_token, :check_if_login_required, :only => [:view]
before_action :add_customer, :only => :new
before_action :view_customer, :except => :new
skip_before_action :verify_authenticity_token, :check_if_login_required, :only => [:view]
default_search_scope :names
autocomplete :customer, :name, :full => true, :extra_data => [:id]
def allowed_params
params.require(:customer).permit(:name, :email, :primary_phone, :mobile_phone, :phone_number)
end
# getter method for a customer's vehicles
# used for customer autocomplete field / issue form
def filter_vehicles_by_customer
@filtered_vehicles = Vehicle.all.where(customer_id: params[:selected_customer])
end
# getter method for a customer's invoices
# used for customer autocomplete field / issue form
def filter_invoices_by_customer
@filtered_invoices = QboInvoice.all.where(customer_id: params[:selected_customer])
end
# getter method for a customer's estimates
# used for customer autocomplete field / issue form
def filter_estimates_by_customer
@filtered_estimates = QboEstimate.all.where(customer_id: params[:selected_customer])
end
# display a list of all customers
def index
if params[:search]
@@ -56,22 +66,24 @@ class CustomersController < ApplicationController
end
end
end
# initialize a new customer
def new
@customer = Customer.new
end
# create a new customer
def create
@customer = Customer.new(params[:customer])
@customer = Customer.new(allowed_params)
if @customer.save
flash[:notice] = "New Customer Created"
redirect_to @customer
else
flash[:error] = @customer.errors.full_messages.to_sentence
flash[:error] = @customer.errors.full_messages.to_sentence
redirect_to new_customer_path
end
end
# display a specific customer
def show
begin
@@ -82,7 +94,7 @@ class CustomersController < ApplicationController
render_404
end
end
# return an HTML form for editing a customer
def edit
begin
@@ -91,12 +103,12 @@ class CustomersController < ApplicationController
render_404
end
end
# update a specific customer
def update
begin
@customer = Customer.find_by_id(params[:id])
if @customer.update_attributes(params[:customer])
if @customer.update_attributes(allowed_params)
flash[:notice] = "Customer updated"
redirect_to @customer
else
@@ -107,7 +119,8 @@ class CustomersController < ApplicationController
render_404
end
end
# delete a customer
def destroy
begin
Customer.find_by_id(params[:id]).destroy
@@ -117,12 +130,12 @@ class CustomersController < ApplicationController
render_404
end
end
# Customer view for an issue
# displays an issue for a customer with a provided security CustomerToken
def view
User.current = User.find_by lastname: 'Anonymous'
@token = CustomerToken.where("token = ? and expires_at > ?", params[:token], Time.now)
@token = @token.first
if @token
@@ -137,10 +150,10 @@ class CustomersController < ApplicationController
Journal.preload_journals_details_custom_fields(@journals)
@journals.select! {|journal| journal.notes? || journal.visible_details.any?}
@journals.reverse! if User.current.wants_comments_in_reverse_order?
@changesets = @issue.changesets.visible.preload(:repository, :user).to_a
@changesets.reverse! if User.current.wants_comments_in_reverse_order?
@relations = @issue.relations.select {|r| r.other_issue(@issue) && r.other_issue(@issue).visible? }
@allowed_statuses = @issue.new_statuses_allowed_to(User.current)
@priorities = IssuePriority.active
@@ -150,17 +163,21 @@ class CustomersController < ApplicationController
render_403
end
end
private
# redmine permission - add customers
def add_customer
global_check_permission(:add_customers)
end
# redmine permission - view customers
def view_customer
global_check_permission(:view_customers)
end
# checks to see if there is only one item in an array
# @return true if array only has one item
def only_one_non_zero?( array )
found_non_zero = false
array.each do |val|

View File

@@ -1,6 +1,6 @@
#The MIT License (MIT)
#
#Copyright (c) 2017 rick barrette
#Copyright (c) 2022 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:
#
@@ -12,16 +12,34 @@ class EstimateController < ApplicationController
include AuthHelper
before_filter :require_user
before_action :require_user
#
# Downloads and forwards the estimate pdf
#
def show
base = QboEstimate.get_base
estimate = base.fetch_by_id(params[:id])
@pdf = base.pdf(estimate)
send_data @pdf, filename: "estimate #{estimate.doc_number}.pdf", :disposition => 'inline', :type => "application/pdf"
e = QboEstimate.find_by_id(params[:id]) if params[:id]
e = QboEstimate.find_by_doc_number(params[:search]) if params[:search]
begin
send_data e.pdf, filename: "estimate #{e.doc_number}.pdf", :disposition => 'inline', :type => "application/pdf"
rescue
redirect_to :back, :flash => { :error => "Estimate not found" }
end
end
#
# Downloads estimate by document number
#
def doc
e = QboEstimate.find_by_doc_number(params[:id]) if params[:id]
e = QboEstimate.find_by_doc_number(params[:search]) if params[:search]
begin
send_data e.pdf, filename: "estimate #{e.doc_number}.pdf", :disposition => 'inline', :type => "application/pdf"
rescue
redirect_to :back, :flash => { :error => "Estimate not found" }
end
end
end

View File

@@ -1,6 +1,6 @@
#The MIT License (MIT)
#
#Copyright (c) 2017 rick barrette
#Copyright (c) 2022 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:
#
@@ -12,8 +12,8 @@ class InvoiceController < ApplicationController
include AuthHelper
before_filter :require_user, :unless => proc {|c| session[:token].nil? }
skip_before_filter :verify_authenticity_token, :check_if_login_required, :unless => proc {|c| session[:token].nil? }
before_action :require_user, :unless => proc {|c| session[:token].nil? }
skip_before_action :verify_authenticity_token, :check_if_login_required, :unless => proc {|c| session[:token].nil? }
#
# Downloads and forwards the invoice pdf

View File

@@ -1,10 +1,8 @@
#The License
#The MIT License (MIT)
#
#Copyright (c) 2018 Rick Barrette - All Rights Reserved
#
#Unauthorized copying of this software and associated documentation files (the "Software"), via any medium is strictly prohibited.
#Copyright (c) 2022 rick barrette
#
#Proprietary and confidential
#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:
#
#The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
#
@@ -16,7 +14,7 @@ class LineItemsController < ApplicationController
include AuthHelper
before_filter :require_user
before_action :require_user
# display all line items for an issue
def index

View File

@@ -1,6 +1,6 @@
#The MIT License (MIT)
#
#Copyright (c) 2017 rick barrette
#Copyright (c) 2022 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:
#
@@ -12,16 +12,16 @@ class PaymentsController < ApplicationController
include AuthHelper
before_filter :check_permissions
before_action :check_permissions
def new
@payment = Payment.new
@customers = Customer.all.sort_by &:name
@accounts = Qbo.get_base(:account).service.query("SELECT Id, Name FROM Account WHERE AccountType = 'Bank' Order By Name")
@accounts = Qbo.get_base(:account).query("SELECT Id, Name FROM Account WHERE AccountType = 'Bank' Order By Name")
@payment_methods = Qbo.get_base(:payment_method).service.all
@payment_methods = Qbo.get_base(:payment_method).all
end
def create

View File

@@ -1,6 +1,6 @@
#The MIT License (MIT)
#
#Copyright (c) 2017 rick barrette
#Copyright (c) 2022 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:
#
@@ -15,8 +15,8 @@ class QboController < ApplicationController
include AuthHelper
before_filter :require_user, :except => :qbo_webhook
skip_before_filter :verify_authenticity_token, :check_if_login_required, :only => [:qbo_webhook]
before_action :require_user, :except => :qbo_webhook
skip_before_action :verify_authenticity_token, :check_if_login_required, :only => [:qbo_webhook]
#
# Called when the QBO Top Menu us shown
@@ -34,32 +34,43 @@ class QboController < ApplicationController
# Called when the user requests that Redmine to connect to QBO
#
def authenticate
callback = qbo_oauth_callback_url
token = Qbo.get_oauth_consumer.get_request_token(:oauth_callback => callback)
session[:qb_request_token] = Marshal.dump(token)
redirect_to("https://appcenter.intuit.com/Connect/Begin?oauth_token=#{token.token}") and return
oauth2_client = Qbo.get_client
callback = Setting.host_name + "/qbo/oauth_callback/"
#callback = qbo_oauth_callback_url
grant_url = oauth2_client.auth_code.authorize_url(redirect_uri: callback, response_type: "code", state: SecureRandom.hex(12), scope: "com.intuit.quickbooks.accounting")
redirect_to grant_url
end
#
# Called by QBO after authentication has been processed
#
def oauth_callback
at = Marshal.load(session[:qb_request_token]).get_access_token(:oauth_verifier => params[:oauth_verifier])
#There can only be one...
Qbo.destroy_all
# Save the authentication information
qbo = Qbo.new
qbo.qb_token = at.token
qbo.qb_secret = at.secret
qbo.token_expires_at = 6.months.from_now.utc
qbo.reconnect_token_at = 5.months.from_now.utc
qbo.company_id = params['realmId']
if qbo.save!
redirect_to qbo_sync_path, :flash => { :notice => "Successfully connected to Quickbooks" }
else
redirect_to plugin_settings_path(:redmine_qbo), :flash => { :error => "Error" }
if params[:state].present?
oauth2_client = Qbo.get_client
# use the state value to retrieve from your backend any information you need to identify the customer in your system
#redirect_uri = qbo_oauth_callback_url
redirect_uri = Setting.host_name + "/qbo/oauth_callback/"
if resp = oauth2_client.auth_code.get_token(params[:code], redirect_uri: redirect_uri)
# Remove the last authentication information
Qbo.delete_all
# Save the authentication information
qbo = Qbo.new
qbo.company_id = params[:realmId]
# Generate Access Token & Serialize it into the database
access_token = OAuth2::AccessToken.new(oauth2_client, resp.token, refresh_token: resp.refresh_token)
qbo.token = access_token.to_hash
qbo.expire = 1.hour.from_now.utc
if qbo.save!
redirect_to qbo_sync_path, :flash => { :notice => "Successfully connected to Quickbooks" }
else
redirect_to plugin_settings_path(:redmine_qbo), :flash => { :error => "Error" }
end
end
end
end
@@ -76,6 +87,8 @@ class QboController < ApplicationController
# Quickbooks Webhook Callback
def qbo_webhook
logger.debug "Quickbooks is calling webhook"
# check the payload
signature = request.headers['intuit-signature']
@@ -99,10 +112,12 @@ class QboController < ApplicationController
# TODO rename all other models!
name.prepend("Qbo") if not name.eql? "Customer"
logger.debug "Casting #{name.constantize} to obj"
# Magicly initialize the correct class
obj = name.constantize
# for merge events
obj.destroy(entity['deletedId']) if entity['deletedId']
@@ -111,7 +126,13 @@ class QboController < ApplicationController
obj.destroy(id)
#if not then update!
else
obj.sync_by_id(id)
begin
obj.sync_by_id(id)
rescue => e
logger.error "Failed to call sync_by_id on obj"
logger.error e.message
logger.error e.backtrace.join("\n")
end
end
end
@@ -123,12 +144,15 @@ class QboController < ApplicationController
else
render nothing: true, status: 400
end
logger.debug "Quickbooks webhook complete"
end
#
# Synchronizes the QboCustomer table with QBO
#
def sync
logger.debug "Syncing EVERYTHING"
# Update info in background
Thread.new do
if Qbo.exists?
@@ -144,6 +168,6 @@ class QboController < ApplicationController
ActiveRecord::Base.connection.close
end
redirect_to :back, :flash => { :notice => "Successfully synced to Quickbooks" }
redirect_to :home, :flash => { :notice => "Successfully synced to Quickbooks" }
end
end

View File

@@ -1,6 +1,6 @@
#The MIT License (MIT)
#
#Copyright (c) 2017 rick barrette
#Copyright (c) 2022 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:
#
@@ -11,11 +11,15 @@
# This controller class will handle map management
class VehiclesController < ApplicationController
unloadable
include AuthHelper
before_filter :require_user
before_action :require_user
def allowed_params
params.require(:vehicle).permit(:year, :make, :model, :customer_id, :notes, :vin)
end
# display a list of all vehicles
def index
if params[:customer_id]
@@ -25,7 +29,8 @@ class VehiclesController < ApplicationController
render_404
end
end
# search for a vehicle by vin
if params[:search]
@vehicles = Vehicle.search(params[:search]).paginate(:page => params[:page])
if only_one_non_zero?(@vehicles)
@@ -42,16 +47,16 @@ class VehiclesController < ApplicationController
# create a new vehicle
def create
@vehicle = Vehicle.new(params[:vehicle])
@vehicle = Vehicle.new(allowed_params)
if @vehicle.save
flash[:notice] = "New Vehicle Created"
redirect_to @vehicle
else
flash[:error] = @vehicle.errors.full_messages.to_sentence
redirect_to new_vehicle_path
flash[:error] = @vehicle.errors.full_messages.to_sentence
redirect_to Vehicle.find_by_vin @vehicle.vin
end
end
# display a specific vehicle
def show
begin
@@ -61,7 +66,7 @@ class VehiclesController < ApplicationController
render_404
end
end
# return an HTML form for editing a vehicle
def edit
begin
@@ -71,23 +76,24 @@ class VehiclesController < ApplicationController
render_404
end
end
# update a specific vehicle
def update
@customer = params[:customer]
begin
begin
@vehicle = Vehicle.find_by_id(params[:id])
if @vehicle.update_attributes(params[:vehicle])
if @vehicle.update_attributes(allowed_params)
flash[:notice] = "Vehicle updated"
redirect_to @vehicle
else
flash[:error] = @vehicle.errors.full_messages.to_sentence if @vehicle.errors
redirect_to edit_vehicle_path
end
#show any errors anyways
flash[:error] = @vehicle.errors.full_messages.to_sentence unless @vehicle.errors.empty?
rescue ActiveRecord::RecordNotFound
render_404
end
end
end
# delete a specific vehicle
def destroy
@@ -99,9 +105,11 @@ class VehiclesController < ApplicationController
render_404
end
end
private
# checks to see if there is only one item in an array
# @return true if array only has one item
def only_one_non_zero?( array )
found_non_zero = false
array.each do |val|
@@ -113,4 +121,4 @@ class VehiclesController < ApplicationController
found_non_zero
end
end
end

View File

@@ -1,6 +1,6 @@
#The MIT License (MIT)
#
#Copyright (c) 2017 rick barrette
#Copyright (c) 2022 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:
#
@@ -17,7 +17,7 @@ class Customer < ActiveRecord::Base
has_many :qbo_estimates
has_many :vehicles
attr_accessible :name, :notes, :email, :primary_phone, :mobile_phone
#attr_accessible :name, :notes, :email, :primary_phone, :mobile_phone, :phone_number
validates_presence_of :id, :name
self.primary_key = :id
@@ -63,6 +63,8 @@ class Customer < ActiveRecord::Base
pn = Quickbooks::Model::TelephoneNumber.new
pn.free_form_number = n
@details.primary_phone = pn
#update our locally stored number too
update_phone_number
end
# Convenience Method
@@ -83,6 +85,26 @@ class Customer < ActiveRecord::Base
pn = Quickbooks::Model::TelephoneNumber.new
pn.free_form_number = n
@details.mobile_phone = pn
#update our locally stored number too
update_mobile_phone_number
end
# update the localy stored phone number as a plain string with no special chars
def update_phone_number
begin
self.phone_number = self.primary_phone.tr('^0-9', '')
rescue
return nil
end
end
# update the localy stored phone number as a plain string with no special chars
def update_mobile_phone_number
begin
self.mobile_phone_number = self.mobile_phone.tr('^0-9', '')
rescue
return nil
end
end
# Convenience Method
@@ -114,7 +136,7 @@ class Customer < ActiveRecord::Base
# proforms a bruteforce sync operation
# This needs to be simplified
def self.sync
service = Qbo.get_base(:customer).service
service = Qbo.get_base(:customer)
# Sync ALL customers if the database is empty
#if count == 0
@@ -142,26 +164,16 @@ class Customer < ActiveRecord::Base
end
end
# Searchs the database for a customer by name
# Searchs the database for a customer by name or phone number with out special chars
def self.search(search)
customers = where("name LIKE ?", "%#{search}%")
#if customers.empty?
# service = Qbo.get_base(:customer).service
# results = service.query("Select Id From Customer Where PrimaryPhone LIKE '%#{search}%' AND Mobile LIKE '%#{search}%'")
# results.each do |customer|
# customers << Customer.find_by_id(customer.id)
# end
#end
customers = where("name LIKE ? OR phone_number LIKE ? OR mobile_phone_number LIKE ?", "%#{search}%", "%#{search}%", "%#{search}%")
return customers.order(:name)
end
# proforms a bruteforce sync operation
# This needs to be simplified
def self.sync_by_id(id)
service = Qbo.get_base(:customer).service
service = Qbo.get_base(:customer)
customer = service.fetch_by_id(id)
qbo_customer = Customer.find_or_create_by(id: customer.id)
@@ -181,7 +193,7 @@ class Customer < ActiveRecord::Base
# Push the updates
def save_with_push
begin
@details = Qbo.get_base(:customer).service.update(@details)
@details = Qbo.get_base(:customer).update(@details)
#raise "QBO Fault" if @details.fault?
self.id = @details.id
rescue Exception => e
@@ -199,7 +211,7 @@ class Customer < ActiveRecord::Base
def pull
begin
raise Exception unless self.id
@details = Qbo.get_base(:customer).find_by_id(self.id)
@details = Qbo.get_base(:customer).fetch_by_id(self.id)
rescue Exception => e
@details = Quickbooks::Model::Customer.new
end

View File

@@ -1,6 +1,6 @@
#The MIT License (MIT)
#
#Copyright (c) 2017 rick barrette
#Copyright (c) 2022 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:
#
@@ -11,7 +11,7 @@
class CustomerToken < ActiveRecord::Base
unloadable
has_many :issues
attr_accessible :token, :expires_at, :issue_id
#attr_accessible :token, :expires_at, :issue_id
validates_presence_of :expires_at, :issue_id
before_create :generate_token

View File

@@ -1,8 +1,8 @@
#Copyright (c) 2018 Rick Barrette - All Rights Reserved
#
#Unauthorized copying of this software and associated documentation files (the "Software"), via any medium is strictly prohibited.
#The MIT License (MIT)
#
#Proprietary and confidential
#Copyright (c) 2022 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:
#
#The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
#
@@ -14,7 +14,7 @@ class LineItem < ActiveRecord::Base
belongs_to :issue
attr_accessible :amount, :description, :unit_price, :quantity, :item_id
#attr_accessible :amount, :description, :unit_price, :quantity, :item_id
validates_presence_of :amount, :description, :unit_price, :quantity
def add_to_invoice(invoice)

View File

@@ -1,6 +1,6 @@
#The MIT License (MIT)
#
#Copyright (c) 2017 rick barrette
#Copyright (c) 2020 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:
#
@@ -23,7 +23,7 @@ class Payment
payment.deposit_to_account_id = @account_id.to_i
payment.payment_method_id = @payment_method_id.to_i
payment.total = @total_amount
Qbo.get_base(:payment).service.update(payment)
Qbo.get_base(:payment).update(payment)
end
def save!

View File

@@ -1,6 +1,6 @@
#The MIT License (MIT)
#
#Copyright (c) 2017 rick barrette
#Copyright (c) 2020 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:
#
@@ -10,34 +10,76 @@
class Qbo < ActiveRecord::Base
unloadable
validates_presence_of :qb_token, :qb_secret, :company_id, :token_expires_at, :reconnect_token_at
#validates_presence_of :qb_token, :qb_secret, :company_id, :token_expires_at, :reconnect_token_at
validates_presence_of :token, :company_id, :expire
serialize :token
OAUTH_CONSUMER_KEY = Setting.plugin_redmine_qbo['settingsOAuthConsumerKey']
OAUTH_CONSUMER_SECRET = Setting.plugin_redmine_qbo['settingsOAuthConsumerSecret']
$qb_oauth_consumer = OAuth::Consumer.new(OAUTH_CONSUMER_KEY, OAUTH_CONSUMER_SECRET, {
:site => "https://oauth.intuit.com",
:request_token_path => "/oauth/v1/get_request_token",
:authorize_url => "https://appcenter.intuit.com/Connect/Begin",
:access_token_path => "/oauth/v1/get_access_token"
})
# Configure quickbooks-ruby-base to access our database
Quickbooks::Base.configure do |c|
c.persistent_token = 'qb_token'
c.persistent_secret = 'qb_secret'
c.persistent_company_id = 'company_id'
#
# Getter for quickbooks OAuth2 client
#
def self.get_client
oauth_params = {
site: "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"
}
return OAuth2::Client.new(OAUTH_CONSUMER_KEY, OAUTH_CONSUMER_SECRET, oauth_params)
end
#
# Getter for oauth consumer
#
def self.get_oauth_consumer
# Quickbooks Config Info
return $qb_oauth_consumer
end
# Get a quickbooks base object for type
#
# Get a quickbooks base service object for type
# @params type of base
#
def self.get_base(type)
Quickbooks::Base.new(first, type)
# lets getnourbold access token from the database
oauth2_client = get_client
qbo = self.first
access_token = OAuth2::AccessToken.from_hash(oauth2_client, qbo.token)
# check to see if we need to refresh the acesstoken
if qbo.expire.to_time.utc.past?
puts "Updating access token"
new_access_token_object = access_token.refresh!
qbo.token = new_access_token_object.to_hash
qbo.expire = 1.hour.from_now.utc
qbo.save!
access_token = new_access_token_object
else
puts "Using current token"
end
# build the reqiested service
case type
when :item
return Quickbooks::Service::Item.new(:company_id => qbo.company_id, :access_token => access_token)
when :time_activity
return Quickbooks::Service::TimeActivity.new(:company_id => qbo.company_id, :access_token => access_token)
when :customer
return Quickbooks::Service::Customer.new(:company_id => qbo.company_id, :access_token => access_token)
when :invoice
return Quickbooks::Service::Invoice.new(:company_id => qbo.company_id, :access_token => access_token)
when :estimate
return Quickbooks::Service::Estimate.new(:company_id => qbo.company_id, :access_token => access_token)
when :account
return Quickbooks::Service::Account.new(:company_id => qbo.company_id, :access_token => access_token)
when :employee
return Quickbooks::Service:: Employee.new(:company_id => qbo.company_id, :access_token => access_token)
else
return access_token
end
end
# Get the QBO account

View File

@@ -1,6 +1,6 @@
#The MIT License (MIT)
#
#Copyright (c) 2017 rick barrette
#Copyright (c) 2022 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:
#
@@ -11,7 +11,7 @@
class QboEmployee < ActiveRecord::Base
unloadable
has_many :users
attr_accessible :name
#attr_accessible :name
validates_presence_of :id, :name
def self.get_base
@@ -19,7 +19,7 @@ class QboEmployee < ActiveRecord::Base
end
def self.sync
employees = get_base.service.all
employees = get_base.all
transaction do
# Update the item table
@@ -33,7 +33,7 @@ class QboEmployee < ActiveRecord::Base
end
def self.sync_by_id(id)
employee = get_base.service.fetch_by_id(id)
employee = get_base.fetch_by_id(id)
qbo_employee = find_or_create_by(id: employee.id)
qbo_employee.name = employee.display_name
qbo_employee.id = employee.id

View File

@@ -1,6 +1,6 @@
#The MIT License (MIT)
#
#Copyright (c) 2017 rick barrette
#Copyright (c) 2022 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:
#
@@ -13,13 +13,13 @@ class QboEstimate < ActiveRecord::Base
has_and_belongs_to_many :issues
belongs_to :customer
attr_accessible :doc_number, :id
#attr_accessible :doc_number, :id
validates_presence_of :doc_number, :id
self.primary_key = :id
# return the QBO Estimate service
def self.get_base
Qbo.get_base(:estimate).service
Qbo.get_base(:estimate)
end
# sync all estimates
@@ -55,4 +55,12 @@ class QboEstimate < ActiveRecord::Base
qbo_estimate.id = estimate.id
qbo_estimate.save!
end
# download the pdf from quickbooks
def pdf
base = QboEstimate.get_base
estimate = base.fetch_by_id(id)
return base.pdf(estimate)
end
end

View File

@@ -1,6 +1,6 @@
#The MIT License (MIT)
#
#Copyright (c) 2017 rick barrette
#Copyright (c) 2022 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:
#
@@ -13,16 +13,17 @@ class QboInvoice < ActiveRecord::Base
has_and_belongs_to_many :issues
belongs_to :customer
attr_accessible :doc_number, :id
#attr_accessible :doc_number, :id
validates_presence_of :doc_number, :id
self.primary_key = :id
def self.get_base
Qbo.get_base(:invoice).service
Qbo.get_base(:invoice)
end
# sync ALL the invoices
def self.sync
logger.debug "Syncing all invoices"
last = Qbo.first.last_sync
query = "SELECT Id, DocNumber FROM Invoice"
@@ -42,6 +43,7 @@ class QboInvoice < ActiveRecord::Base
#sync by invoice ID
def self.sync_by_id(id)
logger.debug "Syncing invoice #{id}"
#update the information in the database
invoice = get_base.fetch_by_id(id)
process_invoice invoice
@@ -56,6 +58,8 @@ class QboInvoice < ActiveRecord::Base
# skip this issue if the issue customer is not the same as the invoice customer
return if issue.customer_id != invoice.customer_ref.value.to_i
logger.debug "Attaching invoice #{invoice.id} to issue #{issue.id}"
# Load the invoice into the database
qbo_invoice = QboInvoice.find_or_create_by(id: invoice.id)
qbo_invoice.doc_number = invoice.doc_number
@@ -73,6 +77,7 @@ class QboInvoice < ActiveRecord::Base
# processes the invoice into the system
def self.process_invoice(invoice)
logger.debug "Processing invoice"
# Check the private notes
if not invoice.private_note.nil?
invoice.private_note.scan(/#(\w+)/).flatten.each { |issue|
@@ -105,6 +110,7 @@ class QboInvoice < ActiveRecord::Base
break if vin.nil?
if not cf.string_value.to_s.eql? vin
cf.string_value = vin.to_s
logger.debug "VIN has changed"
is_changed = true
end
end
@@ -149,7 +155,14 @@ class QboInvoice < ActiveRecord::Base
# Push updates
#invoice.sync_token += 1 if is_changed
get_base.update(invoice) if is_changed
begin
logger.debug "Trying to update invoice"
get_base.update(invoice) if is_changed
rescue
# Do nothing, probaly too many vehicles on the invoice. This is a problem with how it's billed
# TODO Add notes in memo area
logger.error "Failed to update invoice"
end
end
end

View File

@@ -1,6 +1,6 @@
#The MIT License (MIT)
#
#Copyright (c) 2017 rick barrette
#Copyright (c) 2022 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:
#
@@ -11,7 +11,7 @@
class QboItem < ActiveRecord::Base
unloadable
has_many :issues
attr_accessible :name
#attr_accessible :name
validates_presence_of :id, :name
self.primary_key = :id
@@ -27,9 +27,9 @@ class QboItem < ActiveRecord::Base
query << " AND Metadata.LastUpdatedTime >= '#{last.iso8601}' " if last
if count == 0
items = get_base.service.all
items = get_base.all
else
items = get_base.service.query(query)
items = get_base.query(query)
end
unless items.count = 0

View File

@@ -1,6 +1,6 @@
#The MIT License (MIT)
#
#Copyright (c) 2017 rick barrette
#Copyright (c) 2022 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:
#
@@ -12,7 +12,7 @@ class QboPurchase < ActiveRecord::Base
unloadable
belongs_to :issues
belongs_to :qbo_customer
attr_accessible :description
#attr_accessible :description
validates_presence_of :id, :line_id, :description, :qbo_customer_id
def self.get_base
@@ -20,11 +20,11 @@ class QboPurchase < ActiveRecord::Base
end
def get_purchase(id)
get_base.service.find_by_id(id)
get_base.find_by_id(id)
end
def self.sync
QboPurchase.get_base.service.all.each { |purchase|
QboPurchase.get_base.all.each { |purchase|
purchase.line_items.all? { |line_item|

View File

@@ -1,6 +1,6 @@
#The MIT License (MIT)
#
#Copyright (c) 2017 rick barrette
#Copyright (c) 2022 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:
#
@@ -15,12 +15,12 @@ class Vehicle < ActiveRecord::Base
belongs_to :customer
has_many :issues, :foreign_key => 'vehicles_id'
attr_accessible :year, :make, :model, :customer_id, :notes, :vin
#attr_accessible :year, :make, :model, :customer_id, :notes, :vin
validates_presence_of :customer
validates :vin, uniqueness: true
before_save :decode_vin
after_initialize :get_details
#after_find :get_details
self.primary_key = :id
@@ -36,11 +36,13 @@ class Vehicle < ActiveRecord::Base
# returns the raw JSON details from EMUNDS
def details
get_details if @details.nil?
return @details
end
# returns the style of the vehicle
def style
get_details if @details.nil?
begin
return @details.trim if @details
rescue
@@ -57,16 +59,17 @@ class Vehicle < ActiveRecord::Base
# returns the number of doors of the vehicle
def doors
get_details if @details.nil?
return @details.doors if @details
end
# Force Upper Case for VIN numbers
# Force Upper Case for make numbers
def make=(val)
# The to_s is in case you get nil/non-string
write_attribute(:make, val.to_s.titleize)
end
# Force Upper Case for VIN numbers
# Force Upper Case for model numbers
def model=(val)
# The to_s is in case you get nil/non-string
write_attribute(:model, val.to_s.titleize)
@@ -83,22 +86,7 @@ class Vehicle < ActiveRecord::Base
def self.search(search)
where("vin LIKE ?", "%#{search}%")
end
private
# init method to pull JSON details from Edmunds
def get_details
if self.vin?
begin
query = NhtsaVin.get(self.vin)
raise RuntimeError, query.error unless query.valid?
@details = query.response
rescue Exception => e
errors.add(:vin, e.message)
end
end
end
# decodes a vin and updates self
def decode_vin
get_details
@@ -114,4 +102,24 @@ private
self.name = to_s
end
private
# init method to pull JSON details from Edmunds
def get_details
if self.vin?
#validate the vin before calling a remote server
validation = NhtsaVin.validate(self.vin)
begin
#if the vin validation failed, raise an exception and exit
raise RuntimeError, validation.error unless validation.valid?
# query NHTSA for details on the vin
query = NhtsaVin.get(self.vin)
raise RuntimeError, query.error unless query.valid?
@details = query.response
rescue Exception => e
errors.add(:vin, e.message)
end
end
end
end

View File

@@ -1,53 +1,53 @@
<table>
<tbody>
<tr>
<th>Email</th>
<th><%=t(:label_email)%></th>
<td><%= customer.email %></td>
</tr>
<tr>
<th>Primary Phone</th>
<th><%=t(:label_primary_phone)%></th>
<td><%= number_to_phone(customer.primary_phone.gsub(/[^\d]/, '').to_i, area_code: true) if customer.primary_phone %></td>
</tr>
<tr>
<th>Mobile Phone</th>
<th><%=t(:label_mobile_phone)%></th>
<td><%= number_to_phone(customer.mobile_phone.gsub(/[^\d]/, '').to_i, area_code: true) if customer.mobile_phone %></td>
</tr>
<tr>
<th>Bill Address</th>
<th><%=t(:label_billing_address)%></th>
<td><%= customer.billing_address %></td>
</tr>
<tr>
<th>Shipping Address</th>
<th><%=t(:label_shipping_address)%></th>
<td><%= customer.shipping_address %></td>
</tr>
<tr>
<th>Issues</th>
<th><%=t(:issues)%></th>
<td><%= customer.issues.count %></td>
</tr>
<tr>
<th>Account Balance</th>
<th><%=t(:label_account_balance)%></th>
<td>$<%= customer.balance %></td>
</tr>
<tr>
<th>Balance With Jobs</th>
<th><%=t(:label_balance_with_jobs)%></th>
<td>$<%= customer.balance_with_jobs %></td>
</tr>
<tr>
<th>Notes</th>
<th><%=t(:field_notes)%></th>
<td><%= customer.notes %></td>
</tr>
<tr>
<td>
<%= button_to "Edit Customer", edit_customer_path(customer), method: :get%>
<%= button_to t(:label_edit_customer), edit_customer_path(customer), method: :get%>
</td>
</tr>
</tbody>

View File

@@ -5,35 +5,35 @@
<%= form_for @customer do |f| %>
<div class="clearfix">
Display Name:
<%=t(:label_display_name)%>
<div class="input">
<%= f.text_field :name, :required => true %>
</div>
</div>
<div class="clearfix">
Phone Number:
<%=t(:label_primary_phone)%>
<div class="input">
<%= f.telephone_field :primary_phone %>
</div>
</div>
<div class="clearfix">
Mobile Phone Number:
<%=t(:label_mobile_phone)%>:
<div class="input">
<%= f.telephone_field :mobile_phone %>
</div>
</div>
<div class="clearfix">
Email:
<%=t(:label_email)%>:
<div class="input">
<%= f.email_field :email %>
</div>
</div>
<div class="clearfix">
Notes:
<%=t(:field_notes)%>:
<div class="input">
<p>
<%= link_to_function content_tag(:span, l(:button_edit), :class => 'icon icon-edit'), '$(this).hide(); $("#issue_description_and_toolbar").show()' unless @customer.new_record? %>

View File

@@ -1,6 +1,6 @@
<%= form_tag(customers_path, :method => "get", id: "search-form") do %>
<%= text_field_tag :search, params[:search], placeholder: "Search Customers" %>
<%= submit_tag "Search" %>
<%= text_field_tag :search, params[:search], placeholder: t(:label_search_customers) %>
<%= submit_tag t(:label_search) %>
<% end %>
<%= button_to "New Customer", new_customer_path, method: :get%>
<%= button_to "Sync", qbo_sync_path, method: :get%>
<%= button_to t(:label_new_customer), new_customer_path, method: :get%>
<%= button_to t(:label_sync), qbo_sync_path, method: :get%>

View File

@@ -1,2 +1,2 @@
<h3>Customers</h3>
<h3><%=t(:label_customers)%></h3>
<%= render :partial => 'customers/search' %>

View File

@@ -1,3 +1,3 @@
<h1>Edit Customer</h1>
<h1><%=t(:label_edit_customer)%></h1>
<br/>
<%= render :partial => 'customers/form' %>

View File

@@ -1,4 +1,4 @@
<h2>Customers <span style="float:right"> <%= render :partial => 'customers/search' %> </span> </h2>
<h2><%=t(:field_customers)%> <span style="float:right"> <%= render :partial => 'customers/search' %> </span> </h2>
<% if @customers.present? %>
<br/>
<% @customers.each do |c| %>
@@ -9,14 +9,14 @@
</div>
<% end %>
<p>Matching <%= @customers.count %> Customers </p>
<p><%=t(:label_matching)%> <%= @customers.count %> <%=t(:field_customers)%> </p>
<div class="actions">
<%= will_paginate @customers %>
</div>
<% else %>
<p>There are no customers containing the term(s) <%= params[:search] %>.</p>
<p><%=t(:label_no_customers)%> <%= params[:search] %>.</p>
<% end %>
<div>

View File

@@ -1,3 +1,3 @@
<h2>New Customer</h2>
<h2><%=t(:label_new_customer)%></h2>
<br/>
<%= render :partial => 'customers/form' %>

View File

@@ -1,26 +1,28 @@
<div id="content">
<h2>Customer #<%= @customer.id %> - <%= @customer.name %> <span style="float:right"> <%= render :partial => 'customers/search' %> </span> </h2>
<br/>
<h2><%=t(:field_customer)%> #<%= @customer.id %> - <%= @customer.name %> </h2>
<br/>
<div class="subject">
<div><h3>Details:</h3></div>
<div><h3><%=t(:label_details)%>:</h3></div>
</div>
<div class="attributes">
<div class="splitcontent">
<div class="splitcontentleft">
<%= render :partial => 'customers/details', locals: {customer: @customer} %>
</div>
<div class="splitcontentleft">
<h4>Vehicles:</h4>
<h4><%=t(:field_vehicles)%>:</h4>
<%= render :partial => 'vehicles/list' %>
<%= button_to "New Vehicle", new_customer_vehicle_path(@customer), method: :get %>
</div>
</div>
<br/>
<h2>Issues:</h2>
<%= render :partial => 'issues/list_simple', locals: {issues: @issues} %>
<h2><%=t(:label_open_issues)%>:</h2>
<%= render :partial => 'issues/list_simple', locals: {issues: @issues.open} %>
<h2><%=t(:label_closed_issues)%>:</h2>
<%= render :partial => 'issues/list_simple', locals: {issues: (@issues - @issues.open)} %>
</div>
</div>

View File

@@ -6,7 +6,7 @@
<div class="subject">
<%= render_issue_subject_with_tree(@issue) %>
This customer link expires in <%= distance_of_time_in_words(Time.now, @token.expires_at) %>
<%=t(:label_customer_link_expires)%> <%= distance_of_time_in_words(Time.now, @token.expires_at) %>
</div>
<p class="author">
<%= authoring @issue.created_on, @issue.author %>.

View File

@@ -0,0 +1,4 @@
<%= form_tag("/qbo/estimate/doc", :method => "get", id: "est-search-form") do %>
<%= text_field_tag :search, params[:search], placeholder: t(:label_search_estimates) %>
<%= submit_tag t(:label_search), :formtarget => "_blank" %>
<% end %>

View File

@@ -0,0 +1,2 @@
<h3><%=t(:label_estimates) %></h3>
<%= render :partial => 'estimates/search' %>

View File

@@ -5,28 +5,28 @@
<%= form_for @payment do |f| %>
<div class="clearfix">
Customer:
<%=t(:field_customer)%>:
<div class="input">
<%= f.collection_select :customer_id, @customers, :id, :name, include_blank: true, :selected => @customer, :required => true%>
</div>
</div>
<div class="clearfix">
Deposit to Account:
<%=t(:label_deposit_into)%>:
<div class="input">
<%= f.collection_select :account_id, @accounts, :id, :name, include_blank: true, :selected => @account, :required => true%>
</div>
</div>
<div class="clearfix">
Payment Method:
<%=t(:label_payment_method)%>:
<div class="input">
<%= f.collection_select :payment_method_id, @payment_methods, :id, :name, include_blank: true, :selected => @payment_method, :required => true%>
</div>
</div>
<div class="clearfix">
Amount:
<%=t(:label_amount)%>:
<div class="input">
<%= f.number_field :total_amount %>
</div>

View File

@@ -1,3 +1,3 @@
<h1>New Payment</h1>
<h1><%=t(:label_new_payment)%></h1>
<br/>
<%= render :partial => 'payments/form' %>

View File

@@ -1 +1 @@
<%= flash.now[:error] = "Not Authorized" %>
<%= flash.now[:error] = t(:label_401) %>

View File

@@ -0,0 +1,35 @@
<div class="splitcontent">
<div class="splitcontentleft">
<div class="customer_id attribute">
<div class="label"><span><%=t(:field_customer)%></span>:</div>
<div class="value"><%= customer %></div>
</div>
<div class="qbo_estimate_id attribute">
<div class="label"><span><%=t(:field_qbo_estimate)%></span>:</div>
<div class="value"><%= estimate_link %></div>
</div>
<div class="qbo_invoice_id attribute">
<div class="label"><span><%=t(:field_qbo_invoice)%></span>:</div>
<div class="value"><%= invoice_link %></div>
</div>
</div>
<div class="splitcontentleft">
<div class="vehicle attribute">
<div class="label"><span><%=t(:field_vehicle)%></span>:</div>
<div class="value"><%= vehicle %></div>
</div>
<div class="vehicle_vin attribute">
<div class="label"><span><%=t(:field_vin)%></span>:</div>
<div class="value"><%=split_vin[0] if split_vin%><b><%=split_vin[1] if split_vin%></b></div>
</div>
<div class="vehicle_notes attribute">
<div class="label"><span><%=t(:field_notes)%></span>:</div>
<div class="value"><%=notes%></div>
</div>
</div>
</div>

View File

@@ -1 +1 @@
<b>Last Sync: </b> <%= Qbo.last_sync if Qbo.exists? %>
<b><%=t(:label_last_sync)%>: </b> <%= Qbo.last_sync if Qbo.exists? %>

View File

@@ -1,7 +1,7 @@
<!--
The MIT License (MIT)
Copyright (c) 2016 rick barrette
Copyright (c) 2020 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:
@@ -15,14 +15,14 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
<!-- configure the Intuit object: 'grantUrl' is a URL in your application which kicks off the flow, see below -->
<script>
intuit.ipp.anywhere.setup({menuProxy: '/path/to/blue-dot', grantUrl: '<%= qbo_authenticate_url %>'});
intuit.ipp.anywhere.setup({menuProxy: '/path/to/blue-dot', grantUrl: '<%= Setting.host_name %>/qbo/authenticate'});
</script>
<table >
<tbody>
<tr>
<th>Intuit QBO OAuth Consumer Key</th>
<th><%=t(:label_client_id)%></th>
<td>
<input type="text" style="width:350px" id="settingsOAuthConsumerKey"
value="<%= settings['settingsOAuthConsumerKey'] %>"
@@ -31,7 +31,7 @@ intuit.ipp.anywhere.setup({menuProxy: '/path/to/blue-dot', grantUrl: '<%= qbo_au
</tr>
<tr>
<th>Intuit QBO OAuth Consumer Secret</th>
<th><%=t(:label_client_secret)%></th>
<td>
<input type="text" style="width:350px" id="settingsOAuthConsumerSecret"
value="<%= settings['settingsOAuthConsumerSecret'] %>"
@@ -40,7 +40,7 @@ intuit.ipp.anywhere.setup({menuProxy: '/path/to/blue-dot', grantUrl: '<%= qbo_au
</tr>
<tr>
<th>Intuit QBO Webhook Token</th>
<th><%=t(:label_webhook_token)%></th>
<td>
<input type="text" style="width:350px" id="settingsWebhookToken"
value="<%= settings['settingsWebhookToken'] %>"
@@ -49,20 +49,15 @@ intuit.ipp.anywhere.setup({menuProxy: '/path/to/blue-dot', grantUrl: '<%= qbo_au
</tr>
<tr>
<th>Token Expires At</th>
<td><%= if Qbo.exists? then Qbo.first.token_expires_at end %>
</tr>
<tr>
<th>Reconnect Token At</th>
<td><%= if Qbo.exists? then Qbo.first.reconnect_token_at end %>
<th><%=t(:label_oauth_expires)%></th>
<td><%= if Qbo.exists? then Qbo.first.expire end %>
</tr>
</tbody>
</table>
<br/>
Note: You need to authenticate after saving your key and secret above
<%=t(:label_oauth_note)%>
<br/>
<br/>
@@ -73,27 +68,27 @@ Note: You need to authenticate after saving your key and secret above
<br/>
<div>
<b>Customer Count:</b> <%= Customer.count%>
<b><%=t(:label_customer_count)%>:</b> <%= Customer.count%>
</div>
<div>
<b>Item Count:</b> <%= QboItem.count %>
<b><%=t(:label_item_count)%>:</b> <%= QboItem.count %>
</div>
<div>
<b>Employee Count:</b> <%= QboEmployee.count %>
<b><%=t(:label_employee_count)%>:</b> <%= QboEmployee.count %>
</div>
<div>
<b>Invoice Count:</b> <%= QboInvoice.count %>
<b><%=t(:label_invoice_count)%>:</b> <%= QboInvoice.count %>
</div>
<div>
<b>Estimate Count:</b> <%= QboEstimate.count %>
<b><%=t(:label_estimate_count)%>:</b> <%= QboEstimate.count %>
</div>
<br/>
<div>
<b>Last Sync: </b> <%= Qbo.last_sync if Qbo.exists? %> <%= link_to " Sync Now", qbo_sync_path %>
<b><%=t(:label_last_sync)%> </b> <%= Qbo.last_sync if Qbo.exists? %> <%= link_to " Sync Now", qbo_sync_path %>
</div>

View File

@@ -0,0 +1,2 @@
<%= render :partial => 'customers/sidebar' %>
<%= render :partial => 'estimates/sidebar' %>

View File

@@ -1 +1 @@
<%= Customer.count %> Customers - <%= render :partial => 'qbo/last_sync' %>
<%= Customer.count %> <%=t(:field_customers)%> - <%= render :partial => 'qbo/last_sync' %>

View File

@@ -11,32 +11,32 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
-->
<body>
<h1> Redmine Quickbooks</h1>
<h1><%=t(:label_redmine_qbo)%></h1>
<div>
<b>Customer Count:</b> <%= @customer_count.to_s%>
<b><%=t(:label_customer_count)%>:</b> <%= @customer_count.to_s%>
</div>
<div>
<b>Item Count:</b> <%= @qbo_item_count.to_s %>
<b><%=t(:label_item_count)%>:</b> <%= @qbo_item_count.to_s %>
</div>
<div>
<b>Employee Count:</b> <%= @qbo_employee_count.to_s %>
<b><%=t(:label_employee_count)%>:</b> <%= @qbo_employee_count.to_s %>
</div>
<div>
<b>Invoice Count:</b> <%= @qbo_invoice_count.to_s %>
<b><%=t(:label_invoice_count)%>:</b> <%= @qbo_invoice_count.to_s %>
</div>
<div>
<b>Estimate Count:</b> <%= @qbo_estimate_count.to_s %>
<b><%=t(:label_estimate_count)%>:</b> <%= @qbo_estimate_count.to_s %>
</div>
<br/>
<div>
<b>Last Sync: </b> <%= Qbo.last_sync if Qbo.exists? %>
<b><%=t(:label_last_sync)%>: </b> <%= Qbo.last_sync if Qbo.exists? %>
</div>
</body>

View File

@@ -2,41 +2,34 @@
<tbody>
<tr>
<th>Customer</th>
<th><%= t(:field_customer)%></th>
<td><%= link_to vehicle.customer.name, customer_path(vehicle.customer) %></td>
</tr>
<tr>
<th>Vehicle</th>
<th><%= t(:field_vehicle) %></th>
<td><%= vehicle.to_s %></td>
</tr>
<tr>
<th>VIN</th>
<th><%= t(:field_vin) %></th>
<td><%= @vin[0] if @vin %><b><%=@vin[1] if @vin%></b></td>
</tr>
<tr>
<th>Style</th>
<td><%= vehicle.style %></td>
</tr>
<tr>
<th>Notes</th>
<th><%= t(:field_notes) %></th>
<td><%= vehicle.notes %></td>
</tr>
<tr>
<th>Issues</th>
<th> <%= t(:issues) %> </th>
<td><%= vehicle.issues.count %></td>
</tr>
<tr>
<td/>
<td>
<%= button_to "Edit", edit_vehicle_path(vehicle), method: :get%>
<%= button_to "Delete", vehicle, method: :delete, data: {confirm: "You sure?"} %>
<%= button_to t(:label_edit), edit_vehicle_path(vehicle), method: :get%>
<%= button_to t(:label_delete), vehicle, method: :delete, data: {confirm: t(:warn_ru_sure)} %>
</td>
</tr>
</tbody>

View File

@@ -4,43 +4,43 @@
<%= form_for @vehicle do |f| %>
<div class="clearfix">
Customer:
<div class="input">
<%= f.autocomplete_field :customer, autocomplete_customer_name_customers_path, :value => @customer.name, :update_elements => {:id => '#customer_id', :value => '#issue_customer'}, :required => true %>
<%= f.hidden_field :customer_id, :id => "customer_id", :value => @customer.id %>
</div>
<%=t(:field_customer)%>:
<div class="input">
<%= f.autocomplete_field :customer, autocomplete_customer_name_customers_path, :value => @customer.name, :update_elements => {:id => '#customer_id', :value => '#issue_customer'}, :required => true %>
<%= f.hidden_field :customer_id, :id => "customer_id", :value => @customer.id %>
</div>
</div>
<div class="clearfix">
Year:
<%=t(:label_year)%>:
<div class="input">
<%= f.number_field :year %>
</div>
</div>
<div class="clearfix">
Make:
<%=t(:label_make)%>:
<div class="input">
<%= f.text_field :make %>
</div>
</div>
<div class="clearfix">
Model:
<%=t(:label_model)%>:
<div class="input">
<%= f.text_field :model %>
</div>
</div>
<div class="clearfix">
VIN:
<%=t(:field_vin)%>:
<div class="input">
<%= f.text_field :vin , :autofocus => true %>
</div>
</div>
<div class="clearfix">
Notes:
<%=t(:field_notes)%>:
<div class="input">
<%= f.text_area :notes, :cols => 60, :rows => 10, :no_label => true %>
</div>

View File

@@ -21,8 +21,8 @@
<%= will_paginate @vehicles %>
</div>
<p>Matching <%= @vehicles.count %> Vehicles </p>
<p><%=t(:label_matching)%> <%=@vehicles.count%> <%=t(:field_vehicles) %> </p>
<% else %>
<p>There are no vehicles containing the term(s) <%= params[:search] %>.</p>
<p><%=t(:label_no_vehicles)%> <%= params[:search] %>.</p>
<% end %>

View File

@@ -1,4 +1,4 @@
<%= form_tag(vehicles_path, :method => "get", id: "search-form") do %>
<%= text_field_tag :search, params[:search], placeholder: "Search Vehicles by VIN" %>
<%= submit_tag "Search" %>
<%= text_field_tag :search, params[:search], placeholder: t(:label_seach_vin) %>
<%= submit_tag t(:label_search) %>
<% end %>

View File

@@ -1,3 +1,3 @@
<h1>Edit Customer Vehicle</h1>
<h1><%=t(:label_edit_customer_vehicle)%></h1>
<br/>
<%= render :partial => 'vehicles/form' %>

View File

@@ -1,4 +1,4 @@
<h2>Customer Vehicles <span style="float:right"> <%= render :partial => 'vehicles/search' %> </span> </h2>
<h2><%=t(:label_cusomer_vehicles)%> <span style="float:right"> <%= render :partial => 'vehicles/search' %> </span> </h2>
<br/>
<%= render :partial => 'vehicles/list' %>

View File

@@ -1,3 +1,3 @@
<h2>New Customer Vehicle</h2>
<h2><%=t(:label_new_vehicle)%></h2>
<br/>
<%= render :partial => 'vehicles/form' %>

View File

@@ -1,8 +1,14 @@
<h2>Vehicle #<%=@vehicle.id%> <span style="float:right"> <%= render :partial => 'customers/search' %> </span> </h2>
<br/>
<h2><%=t(:field_vehicle)%> #<%=@vehicle.id%> <span style="float:right"> <%= render :partial => 'customers/search' %> </span> </h2>
<br/>
<div style="text-align: left; width:90%;">
<%= render :partial => 'vehicles/details', locals: {vehicle: @vehicle} %>
<%= render :partial => 'issues/list_simple', locals: {issues: @vehicle.issues} %>
<p> <b> <%=t(:label_open_issues)%> </b> </p>
<%= render :partial => 'issues/list_simple', locals: {issues: @vehicle.issues.open} %>
<p> <b> <%=t(:label_closed_issues)%> </b> </p>
<%= render :partial => 'issues/list_simple', locals: {issues: (@vehicle.issues - @vehicle.issues.open)} %>
</div>

View File

@@ -1,6 +1,6 @@
#The MIT License (MIT)
#
#Copyright (c) 2017 rick barrette
#Copyright (c) 2022 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:
#
@@ -9,6 +9,7 @@
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# English strings go here for Rails i18n
# Usage t(:label)
en:
# my_label: "My label"
field_customer: "Customer"
@@ -16,9 +17,60 @@ en:
field_qbo_employee: "Employee"
field_qbo_invoice: "Invoice"
field_qbo_estimate: "Estimate"
field_vehicles: "Vehicle"
field_vehicles: "Vehicles"
field_vehicle: "Vehicle"
field_vin: "VIN"
field_notes: "Notes"
field_qbo_billed: "Billed"
label_week: "Week"
label_search_estimates: "Search Estimates"
label_search: "Search"
label_estimates: "Estimates"
label_401: "Not Authorized"
warn_ru_sure: "You sure?"
label_delete: "Delete"
label_edit: "Edit"
label_year: "Year"
label_make: " Make"
label_model: "Model"
label_no_vehicles: "There are no vehicles containing the term(s)"
label_no_customers: "There are no customers containing the term(s)"
label_matching: "Matching "
label_search_vin: "Search Vehicles by VIN"
label_edit_customer_vehicle: "Edit Customer Vehicle"
label_cusomer_vehicles: "Customer Vehicles"
label_new_vehicle: "New Customer Vehicle"
label_open_issues: "Open Issues"
label_closed_issues: "Closed Issues"
label_sync: "Sync"
label_new_customer: "New Customer"
label_search_customers: "Search Customers"
label_customers: "Customers"
label_edit_customer: "Edit Customer"
label_email: "Email"
label_primary_phone: "Primary Phone"
label_mobile_phone: "Mobile Phone"
label_billing_address: "Billing Address"
label_shipping_address: "Shipping Address"
label_account_balance: "Account Balance"
label_balance_with_jobs: "Balance With Jobs"
label_display_name: "Display Name"
label_details: "Details"
label_customer_link_expires: "This customer link expires in"
label_new_payment: "New Payment"
label_amount: "Amount"
label_payment_method: "Payment Method"
label_deposit_into: "Deposit to Account"
label_last_sync: "Last Sync"
label_redmine_qbo: "Redmine Quickbooks"
label_customer_count: "Customer Count"
label_invoice_count: "Invoice Count"
label_estimate_count: "Estimate Count"
label_item_count: "Item Count"
label_employee_count: "Employee Count"
label_client_id: "Intuit QBO OAuth2 Client ID"
label_client_secret: "Intuit QBO OAuth2 Client Secret"
label_webhook_token: "Intuit QBO Webhook Token"
label_oauth_expires: "OAuth2 Access Token Expires At"
label_oauth_note: "Note: You need to authenticate with Quickbooks after saving your key and secret above"
field_customers: "Customers"

View File

@@ -20,6 +20,7 @@ get 'qbo/sync', :to => 'qbo#sync'
# Estimate & Invoice PDF
get 'qbo/estimate/:id', :to => 'estimate#show', as: :estimate
get 'qbo/estimate/doc/:id', :to => 'estimate#doc', as: :estimate_doc
get 'qbo/invoice/:id', :to => 'invoice#show', as: :invoice
#manual billing
@@ -47,3 +48,5 @@ end
#allow for just vehicles too
resources :vehicles
#resources :qbo_estimates

View File

@@ -1,6 +1,6 @@
#The MIT License (MIT)
#
#Copyright (c) 2016 rick barrette
#Copyright (c) 2022 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:
#
@@ -8,7 +8,7 @@
#
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class CreateQbos < ActiveRecord::Migration
class CreateQbos < ActiveRecord::Migration[5.1]
def change
create_table :qbos do |t|

View File

@@ -1,6 +1,6 @@
#The MIT License (MIT)
#
#Copyright (c) 2016 rick barrette
#Copyright (c) 2022 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:
#
@@ -8,7 +8,7 @@
#
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class CreateQboCustomers < ActiveRecord::Migration
class CreateQboCustomers < ActiveRecord::Migration[5.1]
def change
create_table :qbo_customers, id: false do |t|
t.integer :id, :options => 'PRIMARY KEY'

View File

@@ -1,6 +1,6 @@
#The MIT License (MIT)
#
#Copyright (c) 2016 rick barrette
#Copyright (c) 2022 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:
#
@@ -8,7 +8,7 @@
#
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class UpdateIssues < ActiveRecord::Migration
class UpdateIssues < ActiveRecord::Migration[5.1]
def change
add_reference :issues, :qbo_customer, index: true
add_reference :issues, :qbo_item, index: true

View File

@@ -1,6 +1,6 @@
#The MIT License (MIT)
#
#Copyright (c) 2016 rick barrette
#Copyright (c) 2022 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:
#
@@ -8,7 +8,7 @@
#
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class CreateQboItems < ActiveRecord::Migration
class CreateQboItems < ActiveRecord::Migration[5.1]
def change
create_table :qbo_items, id: false do |t|
t.integer :id, :options => 'PRIMARY KEY'

View File

@@ -1,6 +1,6 @@
#The MIT License (MIT)
#
#Copyright (c) 2016 rick barrette
#Copyright (c) 2022 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:
#
@@ -8,7 +8,7 @@
#
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class CreateQboEmployees < ActiveRecord::Migration
class CreateQboEmployees < ActiveRecord::Migration[5.1]
def change
create_table :qbo_employees, id: false do |t|
t.integer :id, :options => 'PRIMARY KEY'

View File

@@ -1,6 +1,6 @@
#The MIT License (MIT)
#
#Copyright (c) 2016 rick barrette
#Copyright (c) 2022 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:
#
@@ -8,7 +8,7 @@
#
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class UpdateUsers < ActiveRecord::Migration
class UpdateUsers < ActiveRecord::Migration[5.1]
def change
add_reference :users, :qbo_employee, index: true
end

View File

@@ -1,6 +1,6 @@
#The MIT License (MIT)
#
#Copyright (c) 2016 rick barrette
#Copyright (c) 2022 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:
#
@@ -8,7 +8,7 @@
#
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class UpdateTimeEntries < ActiveRecord::Migration
class UpdateTimeEntries < ActiveRecord::Migration[5.1]
def change
add_column :time_entries, :qbo_billed, :boolean, :default => false
end

View File

@@ -1,6 +1,6 @@
#The MIT License (MIT)
#
#Copyright (c) 2016 rick barrette
#Copyright (c) 2022 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:
#
@@ -8,7 +8,7 @@
#
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class CreateQboEstimates < ActiveRecord::Migration
class CreateQboEstimates < ActiveRecord::Migration[5.1]
def change
create_table :qbo_estimates, id: false do |t|
t.integer :id, :options => 'PRIMARY KEY'

View File

@@ -1,6 +1,6 @@
#The MIT License (MIT)
#
#Copyright (c) 2016 rick barrette
#Copyright (c) 2022 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:
#
@@ -8,7 +8,7 @@
#
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class UpdateQbos < ActiveRecord::Migration
class UpdateQbos < ActiveRecord::Migration[5.1]
def change
rename_column :qbos, :token, :qb_token
rename_column :qbos, :secret, :qb_secret

View File

@@ -1,6 +1,6 @@
#The MIT License (MIT)
#
#Copyright (c) 2016 rick barrette
#Copyright (c) 2022 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:
#
@@ -8,7 +8,7 @@
#
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class UpdateIssuesWithEstimates < ActiveRecord::Migration
class UpdateIssuesWithEstimates < ActiveRecord::Migration[5.1]
def change
add_reference :issues, :qbo_estimate, index: true
end

View File

@@ -1,6 +1,6 @@
#The MIT License (MIT)
#
#Copyright (c) 2016 rick barrette
#Copyright (c) 2022 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:
#
@@ -8,7 +8,7 @@
#
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class CreateQboInvoices < ActiveRecord::Migration
class CreateQboInvoices < ActiveRecord::Migration[5.1]
def change
create_table :qbo_invoices, id: false do |t|
t.integer :id, :options => 'PRIMARY KEY'

View File

@@ -1,6 +1,6 @@
#The MIT License (MIT)
#
#Copyright (c) 2016 rick barrette
#Copyright (c) 2022 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:
#
@@ -8,7 +8,7 @@
#
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class UpdateIssuesWithInvoices< ActiveRecord::Migration
class UpdateIssuesWithInvoices< ActiveRecord::Migration[5.1]
def change
add_reference :issues, :qbo_invoice, index: true
end

View File

@@ -1,6 +1,6 @@
#The MIT License (MIT)
#
#Copyright (c) 2016 rick barrette
#Copyright (c) 2022 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:
#
@@ -8,7 +8,7 @@
#
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class CreateQboPurchases< ActiveRecord::Migration
class CreateQboPurchases< ActiveRecord::Migration[5.1]
def change
create_table :qbo_purchases, id: false do |t|
t.integer :id, :options => 'PRIMARY KEY'

View File

@@ -1,6 +1,6 @@
#The MIT License (MIT)
#
#Copyright (c) 2016 rick barrette
#Copyright (c) 2022 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:
#
@@ -8,7 +8,7 @@
#
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class UpdateCustomers < ActiveRecord::Migration
class UpdateCustomers < ActiveRecord::Migration[5.1]
def change
add_reference :qbo_customers, :qbo_purchase, index: true
end

View File

@@ -1,6 +1,6 @@
#The MIT License (MIT)
#
#Copyright (c) 2016 rick barrette
#Copyright (c) 2022 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:
#
@@ -8,7 +8,7 @@
#
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class UpdateQboPurchases < ActiveRecord::Migration
class UpdateQboPurchases < ActiveRecord::Migration[5.1]
def change
rename_column :qbo_purchases, :customer_id, :qbo_customer_id
end

View File

@@ -1,6 +1,6 @@
#The MIT License (MIT)
#
#Copyright (c) 2016 rick barrette
#Copyright (c) 2022 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:
#
@@ -8,7 +8,7 @@
#
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class CreateVehicles < ActiveRecord::Migration
class CreateVehicles < ActiveRecord::Migration[5.1]
def change
create_table :vehicles do |t|

View File

@@ -1,6 +1,6 @@
#The MIT License (MIT)
#
#Copyright (c) 2016 rick barrette
#Copyright (c) 2022 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:
#
@@ -8,7 +8,7 @@
#
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class UpdateIssuesWithVehicles < ActiveRecord::Migration
class UpdateIssuesWithVehicles < ActiveRecord::Migration[5.1]
def change
add_reference :issues, :vehicles, index: true
end

View File

@@ -1,6 +1,6 @@
#The MIT License (MIT)
#
#Copyright (c) 2016 rick barrette
#Copyright (c) 2022 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:
#
@@ -8,7 +8,7 @@
#
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class UpdateVehicles < ActiveRecord::Migration
class UpdateVehicles < ActiveRecord::Migration[5.1]
def change
add_column :vehicles, :name, :text
end

View File

@@ -1,6 +1,6 @@
#The MIT License (MIT)
#
#Copyright (c) 2016 rick barrette
#Copyright (c) 2022 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:
#
@@ -8,7 +8,7 @@
#
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class QbocustomersToCustomers< ActiveRecord::Migration
class QbocustomersToCustomers< ActiveRecord::Migration[5.1]
def change
rename_table :qbo_customers, :customers
rename_column :issues, :qbo_customer_id, :customer_id

View File

@@ -1,6 +1,6 @@
#The MIT License (MIT)
#
#Copyright (c) 2016 rick barrette
#Copyright (c) 2022 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:
#
@@ -8,7 +8,7 @@
#
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class UpdateQbosTimeStamp < ActiveRecord::Migration
class UpdateQbosTimeStamp < ActiveRecord::Migration[5.1]
def change
add_column :qbos, :last_sync, :datetime
end

View File

@@ -1,6 +1,6 @@
#The MIT License (MIT)
#
#Copyright (c) 2016 rick barrette
#Copyright (c) 2022 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:
#
@@ -8,7 +8,7 @@
#
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class AddIssuesQboInvoices < ActiveRecord::Migration
class AddIssuesQboInvoices < ActiveRecord::Migration[5.1]
def self.up
create_table :issues_qbo_invoices, :id => false do |t|
t.references :issue

View File

@@ -1,6 +1,6 @@
#The MIT License (MIT)
#
#Copyright (c) 2016 rick barrette
#Copyright (c) 2022 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:
#
@@ -8,7 +8,7 @@
#
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class UpdateIssuesRemoveInvoice < ActiveRecord::Migration
class UpdateIssuesRemoveInvoice < ActiveRecord::Migration[5.1]
def change
remove_reference :issues, :qbo_invoice
end

View File

@@ -1,6 +1,6 @@
#The MIT License (MIT)
#
#Copyright (c) 2016 rick barrette
#Copyright (c) 2022 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:
#
@@ -8,7 +8,7 @@
#
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class CreateCustomerTokens < ActiveRecord::Migration
class CreateCustomerTokens < ActiveRecord::Migration[5.1]
def change
create_table :customer_tokens do |t|
t.string :token

View File

@@ -1,6 +1,6 @@
#The MIT License (MIT)
#
#Copyright (c) 2017 rick barrette
#Copyright (c) 2022 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:
#
@@ -8,7 +8,7 @@
#
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class UpdateInvoicesAndEstimates < ActiveRecord::Migration
class UpdateInvoicesAndEstimates < ActiveRecord::Migration[5.1]
def change
add_reference :qbo_invoices, :customer, index: true
add_reference :qbo_estimates, :customer, index: true

View File

@@ -1,6 +1,6 @@
#The MIT License (MIT)
#
#Copyright (c) 2017 rick barrette
#Copyright (c) 2022 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:
#
@@ -8,7 +8,7 @@
#
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class UpdateProjects < ActiveRecord::Migration
class UpdateProjects < ActiveRecord::Migration[5.1]
def change
add_reference :projects, :customer, index: true
add_reference :projects, :vehicle, index: true

View File

@@ -1,6 +1,6 @@
#The License
#
#Copyright (c) 2018 Rick Barrette - All Rights Reserved
#Copyright (c) 2022 Rick Barrette - All Rights Reserved
#
#Unauthorized copying of this software and associated documentation files (the "Software"), via any medium is strictly prohibited.
#
@@ -10,7 +10,7 @@
#
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class CreateLineItems < ActiveRecord::Migration
class CreateLineItems < ActiveRecord::Migration[5.1]
def change
create_table :line_items do |t|
t.integer :item_id

View File

@@ -0,0 +1,15 @@
#The MIT License (MIT)
#
#Copyright (c) 2022 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:
#
#The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
#
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class AddCustomersPhoneNumber < ActiveRecord::Migration[5.1]
def change
add_column :customers, :phone_number, :string
end
end

View File

@@ -0,0 +1,15 @@
#The MIT License (MIT)
#
#Copyright (c) 2022 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:
#
#The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
#
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class AddCustomersMobilePhoneNumber < ActiveRecord::Migration[5.1]
def change
add_column :customers, :mobile_phone_number, :string
end
end

View File

@@ -1,6 +1,6 @@
#The MIT License (MIT)
#
#Copyright (c) 2017 rick barrette
#Copyright (c) 2022 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:
#
@@ -8,11 +8,10 @@
#
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# This sidekiq worker class will handle emailing weekly time reports
class EmailWorker
include Sidekiq::Worker
class UpdateQbosTypes < ActiveRecord::Migration[5.1]
def perform()
# email something
def change
change_column :qbos, :qb_token, :text
change_column :qbos, :qb_secret, :text
end
end

View File

@@ -0,0 +1,17 @@
#The MIT License (MIT)
#
#Copyright (c) 2022 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:
#
#The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
#
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class UpdateQbosToken < ActiveRecord::Migration[5.1]
def change
add_column :qbos, :token, :text
add_column :qbos, :expire, :datetime
end
end

View File

@@ -0,0 +1,18 @@
#The MIT License (MIT)
#
#Copyright (c) 2022 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:
#
#The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
#
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class RemoveQbosKeys < ActiveRecord::Migration[5.1]
def change
remove_column :qbos, :qb_secret
remove_column :qbos, :token_expires_at
remove_column :qbos, :reconnect_token_at
remove_column :qbos, :qb_token
end
end

View File

@@ -1,6 +1,6 @@
#The MIT License (MIT)
#
#Copyright (c) 2017 rick barrette
#Copyright (c) 2022 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:
#
@@ -28,10 +28,11 @@ Redmine::Plugin.register :redmine_qbo do
require_dependency 'pdf_patch'
require_dependency 'attachments_controller_patch'
# About
name 'Redmine Quickbooks Online plugin'
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'
version '0.7.0'
version '1.0.0'
url 'https://github.com/rickbarrette/redmine_qbo'
author_url 'http://rickbarrette.org'
settings :default => {'empty' => true}, :partial => 'qbo/settings'
@@ -53,6 +54,7 @@ Redmine::Plugin.register :redmine_qbo do
# set per_page globally
WillPaginate.per_page = 20
# Permissions for security
permission :view_customers, :customers => :index, :public => false
permission :add_customers, :customers => :new, :public => false
permission :view_payments, :payments => :index, :public => false

View File

@@ -1,6 +1,6 @@
#The MIT License (MIT)
#
#Copyright (c) 2017 rick barrette
#Copyright (c) 2020 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:
#
@@ -42,38 +42,46 @@ module IssuePatch
# Create billable time entries
def bill_time
# Check to see if we have everything we need to bill the customer
#return unless status.is_closed?
return if assigned_to.nil?
return unless Qbo.first
return unless customer
# Get unbilled time entries
spent_time = time_entries.where(qbo_billed: [false, nil])
spent_hours ||= spent_time.sum(:hours) || 0
if spent_hours > 0 then
# Prepare to create a new Time Activity
time_service = Qbo.get_base(:time_activity).service
item_service = Qbo.get_base(:item).service
time_service = Qbo.get_base(:time_activity)
item_service = Qbo.get_base(:item)
time_entry = Quickbooks::Model::TimeActivity.new
# Lets total up each activity before billing.
# This will simpify the invoicing with a single billable time entry per time activity
h = Hash.new(0)
spent_time.each do |entry|
# Lets tottal up each activity
h[entry.activity.name] += entry.hours
# update time entries billed status
entry.qbo_billed = true
entry.save
end
# Now letes upload our totals for each activity as their own billable time entry
h.each do |key, val|
# Convert float spent time to hours and minutes
hours = val.to_i
minutesDecimal = (( val - hours) * 60)
minutes = minutesDecimal.to_i
# Lets match the activity to an qbo item
item = item_service.query("SELECT * FROM Item WHERE Name = '#{key}' ").first
next if item.nil?
# Create the new billable time entry and upload it
time_entry.description = "#{tracker} ##{id}: #{subject} #{"(Partial @ #{done_ratio}%)" if not closed?}"
# TODO entry.user.qbo_employee.id
time_entry.employee_id = assigned_to.qbo_employee_id

View File

@@ -9,33 +9,42 @@
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class IssuesFormHookListener < Redmine::Hook::ViewListener
# Load the javascript
def view_layouts_base_html_head(context = {})
js = javascript_include_tag 'application', :plugin => 'redmine_qbo'
js += javascript_include_tag 'autocomplete-rails', :plugin => 'redmine_qbo'
return js
end
# Edit Issue Form
# Show a dropdown for quickbooks contacts
def view_issues_form_details_bottom(context={})
f = context[:form]
#check project level customer/vehicle ownership first
selected_customer = context[:project].customer ? context[:project].customer.id : nil
selected_vehicle = context[:project].vehicle ? context[:project].vehicle.id : nil
if context[:project]
selected_customer = context[:project].customer ? context[:project].customer.id : nil
selected_vehicle = context[:project].vehicle ? context[:project].vehicle.id : nil
end
# Check to see if there is a quickbooks user attached to the issue
selected_customer = context[:issue].customer ? context[:issue].customer.id : nil
selected_estimate = context[:issue].qbo_estimate ? context[:issue].qbo_estimate.id : nil
selected_vehicle = context[:issue].vehicles_id ? context[:issue].vehicles_id : nil
# Load customer information
customer = Customer.find_by_id(selected_customer) if selected_customer
search_customer = f.autocomplete_field :customer, autocomplete_customer_name_customers_path, :selected => selected_customer, :update_elements => {:id => '#issue_customer_id', :value => '#issue_customer'}
customer_id = f.hidden_field :customer_id, :id => "issue_customer_id"
customer = Customer.find_by_id(selected_customer) if selected_customer
search_customer = f.autocomplete_field :customer,
autocomplete_customer_name_customers_path,
:selected => selected_customer,
:update_elements => { :id => '#issue_customer_id', :value => '#issue_customer' }
customer_id = f.hidden_field :customer_id,
:id => "issue_customer_id",
:onchange => "updateIssueFrom('/issues/#{context[:issue].id}/edit.js', this)"
if context[:issue].customer
if customer.vehicles
vehicles = customer.vehicles.pluck(:name, :id)
@@ -47,12 +56,12 @@ class IssuesFormHookListener < Redmine::Hook::ViewListener
vehicles = [nil].compact
estimates = [nil].compact
end
# Generate the drop down list of quickbooks extimates
select_estimate = f.select :qbo_estimate_id, estimates, :selected => selected_estimate, include_blank: true
vehicle = f.select :vehicles_id, vehicles, :selected => selected_vehicle, include_blank: true
return "<p><label for=\"issue_customer\">Customer</label>#{search_customer} #{customer_id}</p> <p>#{select_estimate}</p> <p>#{vehicle}</p>"
end
end

View File

@@ -10,47 +10,16 @@
class IssuesSaveHookListener < Redmine::Hook::ViewListener
#Before Issue Saved
# Called Before Issue Saved
def controller_issues_edit_before_save(context={})
issue = context[:issue]
# Check to see if we have registered with QBO
if Qbo.first && issue.customer && issue. qbo_item_id
# if this is a quote, lets create a new estimate based off estimated hours
if issue.tracker.name = "Quote" && issue.status.name = "New" && issue.qbo_estimate
# Get QBO Services
item_service = QboItem.get_base.service
estimate_base = QboEstimate.get_base
# Create the estimate
estimate = estimate_base.qr_model(:estimate)
estimate.customer_id = issue.customer_id
estimate.txn_date = Date.today
# Create the line item for labor
item = item_service.fetch_by_id(issue.qbo_item_id)
line_item = Quickbooks::Model::InvoiceLineItem.new
line_item.amount = item.unit_price * issue.estimated_hours
line_item.description = issue.subject
line_item.sales_item! do |detail|
detail.unit_price = item.unit_price
detail.quantity = issue.estimated_hours
detail.item_id = issue.qbo_item_id
end
# Add the line items to the estimate
estimate.line_items << line_item
end
end
issue.subject = issue.subject.titleize
end
# Called After Issue Saved
# Called After Issue Saved
def controller_issues_edit_after_save(context={})
issue = context[:issue]
issue.bill_time if Qbo.first && issue.customer && issue.status.is_closed?
issue.bill_time if issue.status.is_closed?
end
end

View File

@@ -10,11 +10,6 @@
class IssuesShowHookListener < Redmine::Hook::ViewListener
# Additional context fields
# :issue => the issue this is edited
# :f => the form object to create additional fields
#render_on :view_issues_show_details_bottom, :partial => 'hooks/redmine_qbo/_view_issues_show_details_bottom.html.erb'
# View Issue
# Display the quickbooks contact in the issue
def view_issues_show_details_bottom(context={})
@@ -37,6 +32,7 @@ class IssuesShowHookListener < Redmine::Hook::ViewListener
issue.qbo_invoice_ids.each do |i|
invoice = QboInvoice.find i
invoice_link = invoice_link + link_to( invoice.doc_number, "#{Redmine::Utils::relative_url_root}/qbo/invoice/#{i}", :target => "_blank").to_s + " "
invoice_link = invoice_link.html_safe
end
end
@@ -50,46 +46,20 @@ class IssuesShowHookListener < Redmine::Hook::ViewListener
end
split_vin = vin.scan(/.{1,9}/) if vin
return "
<div class=\"splitcontent\">
<div class=\"splitcontentleft\">
<div class=\"customer_id attribute\">
<div class=\"label\"><span>Customer</span>:</div>
<div class=\"value\">#{customer}</div>
</div>
<div class=\"qbo_estimate_id attribute\">
<div class=\"label\"><span>Estimate</span>:</div>
<div class=\"value\">#{estimate_link}</div>
</div>
<div class=\"qbo_invoice_id attribute\">
<div class=\"label\"><span>Invoice</span>:</div>
<div class=\"value\">#{invoice_link}</div>
</div>
</div>
<div class=\"splitcontentleft\">
<div class=\"vehicle attribute\">
<div class=\"label\"><span>Vehicle</span>:</div>
<div class=\"value\">#{vehicle}</div>
</div>
<div class=\"vehicle_vin attribute\">
<div class=\"label\"><span>VIN</span>:</div>
<div class=\"value\">#{split_vin[0] if split_vin}<b>#{split_vin[1] if split_vin}</b></div>
</div>
<div class=\"vehicle_notes attribute\">
<div class=\"label\"><span>Notes</span>:</div>
<div class=\"value\">#{notes}</div>
</div>
</div>
</div>"
context[:controller].send(:render_to_string, {
:partial => 'qbo/issues_show_details',
locals: {
customer: customer,
estimate_link: estimate_link,
invoice_link: invoice_link,
vehicle: vehicle,
split_vin: split_vin,
notes: notes
}
})
end
def view_issues_show_description_bottom(context={})
bill_button = button_to "Bill Time", "#{Redmine::Utils::relative_url_root}/qbo/bill/#{context[:issue].id}", method: :get if User.current.admin?
share_button = button_to "Share", "#{Redmine::Utils::relative_url_root}/customers/view/#{context[:issue].share_token.token}", method: :get if User.current.logged?

View File

@@ -1,3 +1,13 @@
#The MIT License (MIT)
#
#Copyright (c) 2022 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:
#
#The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
#
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
require_dependency 'redmine/export/pdf'
require_dependency 'redmine/export/pdf/issues_pdf_helper'
@@ -7,7 +17,9 @@ module IssuesPdfHelperPatch
base.send(:include, InstanceMethods)
base.class_eval do
unloadable # Send unloadable so it will not be unloaded in development
alias_method_chain :issue_to_pdf, :patch
alias_method :issue_to_pdf, :issue_to_pdf_with_patch
alias_method :issue_to_pdf_with_patch, :issue_to_pdf
end
end

View File

@@ -1,6 +1,6 @@
#The MIT License (MIT)
#
#Copyright (c) 2017 rick barrette
#Copyright (c) 2022 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:
#
@@ -11,62 +11,24 @@
require_dependency 'issue_query'
module QueryPatch
def self.included(base) # :nodoc:
base.extend(ClassMethods)
base.send(:include, InstanceMethods)
# Same as typing in the class
base.class_eval do
unloadable # Send unloadable so it will not be unloaded in development
alias_method_chain :available_columns, :qbo
alias_method_chain :available_filters, :qbo
# Add qbo options to the aviable columns
def available_columns
unless @available_columns
@available_columns = self.class.available_columns.dup
@available_columns << QueryColumn.new(:customer, :sortable => "#{Customer.table_name}.name", :groupable => true, :caption => :field_customer)
@available_columns << QueryColumn.new(:qbo_billed, :sortable => "#{TimeEntry.table_name}.qbo_billed", :groupable => true, :caption => :field_qbo_billed)
end
end
module ClassMethods
super
end
module InstanceMethods
def available_columns_with_qbo
unless @available_columns
@available_columns = available_columns_without_qbo
@available_columns << QueryColumn.new(:customer, :sortable => "#{Customer.table_name}.name", :groupable => true, :caption => :field_customer)
@available_columns << QueryColumn.new(:qbo_billed, :sortable => "#{TimeEntry.table_name}.qbo_billed", :groupable => true, :caption => :field_qbo_billed)
end
@available_columns
end
def available_filters_with_qbo
unless @available_filters
@available_filters = available_filters_without_qbo
#qbo_filters = {
# :customer => {
# :id => l(:field_customer),
# :type => :integer,
# :order => @available_filters.size + 1},
#}
#qbo_filters = {
# "customer_id" => {
# :id => :customer_id,
# :type => :list_optional
#:order => @available_filters.size + 1,
#:values => Customer.find(:all).collect { |c| [c.name, c.id.to_s]}
# }
#}
#@available_filters.merge!(qbo_filters)
end
@available_filters
end
# Add customers to filters
def initialize_available_filters
add_available_filter "customer", :type => :text
super
end
end
# Add module to Issue
IssueQuery.send(:include, QueryPatch)
IssueQuery.send(:prepend, QueryPatch)

View File

@@ -1,6 +1,6 @@
#The MIT License (MIT)
#
#Copyright (c) 2017 rick barrette
#Copyright (c) 2022 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:
#
@@ -12,60 +12,22 @@ require_dependency 'time_entry_query'
module TimeEntryQueryPatch
def self.included(base) # :nodoc:
base.extend(ClassMethods)
base.send(:include, InstanceMethods)
# Same as typing in the class
base.class_eval do
unloadable # Send unloadable so it will not be unloaded in development
alias_method_chain :available_columns, :qbo_billed
alias_method_chain :available_filters, :qbo_billed
# Add QBO options to columns
def available_columns
unless @available_columns
@available_columns = self.class.available_columns.dup
@available_columns << QueryColumn.new(:qbo_billed, :sortable => "#{TimeEntry.table_name}.name", :groupable => true, :caption => :field_qbo_billed)
end
end
module ClassMethods
super
end
module InstanceMethods
def available_columns_with_qbo_billed
unless @available_columns
@available_columns = available_columns_without_qbo
@available_columns << QueryColumn.new(:qbo_billed, :sortable => "#{TimeEntry.table_name}.name", :groupable => true, :caption => :field_qbo_billed)
end
@available_columns
end
def available_filters_with_qbo_billed
unless @available_filters
@available_filters = available_filters_without_qbo
#qbo_filters = {
# :customer => {
# :id => l(:field_qbo_billed),
# :type => :boolean,
# :order => @available_filters.size + 1},
#}
qbo_filters = {
"qbo_billed" => {
:id => :qbo_billed,
:type => :list_optional,
:order => @available_filters.size + 1,
#:values => Customer.find(:all).collect { |c| [c.name, c.id.to_s]}
}
}
@available_filters.merge!(qbo_filters)
end
@available_filters
end
# Add QBO options to the filter
def initialize_available_filters
add_available_filter "qbo_billed", :type => :boolean
super
end
end
# Add module to TimeEntryQuery
TimeEntryQuery.send(:include, QueryPatch)
TimeEntryQuery.send(:prepend, QueryPatch)

View File

@@ -1,3 +1,3 @@
class ViewHookListener < Redmine::Hook::ViewListener
render_on :view_issues_sidebar_issues_bottom, :partial => "customers/sidebar"
render_on :view_layouts_base_sidebar, :partial => "qbo/sidebar"
end