Compare commits
219 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 19733c3f8c | |||
| f22795ac90 | |||
| 166a9ee31b | |||
| 4d85c24872 | |||
| 43c7374c42 | |||
| 60857e9dca | |||
| d38f0d6ac1 | |||
| f6da031e72 | |||
| 9779437c00 | |||
| 1a37926628 | |||
| dac9a7c756 | |||
| 9ac1261ed0 | |||
| 9b69d3f728 | |||
| a5de879260 | |||
| 6464e1cbc6 | |||
| 7f3a94229a | |||
| 395e0117fb | |||
| e04d363e42 | |||
| 3b6c0d4a70 | |||
| d1f6ccd9cb | |||
| 74f7ba41df | |||
| 4fb424faa8 | |||
| 63218e7f42 | |||
| 7f0bb3cae7 | |||
| ad7417c233 | |||
| cf0be2336b | |||
| 6e08746611 | |||
| 7eb26facaf | |||
| 9115cc662c | |||
| 9e7c1dbfb2 | |||
| e99f5d2e52 | |||
| 039d1ca993 | |||
| dd9ac3c481 | |||
| 4f789080e7 | |||
| 80fc858a35 | |||
| 6f8d280657 | |||
| 5782cbc166 | |||
| 0729d2ac41 | |||
| 6c6de0ba86 | |||
| 11dbcaf80c | |||
| 95592e542f | |||
| 472bdec4fa | |||
| c7a313e9ed | |||
| c14b590083 | |||
| 040c920481 | |||
| 8c63817950 | |||
| e2f43d398f | |||
| 7ba4829066 | |||
| 938999db91 | |||
| 0b60a8e41b | |||
| 817a43e849 | |||
| 047296329e | |||
| c8cb74f3d4 | |||
| aceb6cb6b5 | |||
| 9fd1bc9dff | |||
| 04391f1c6e | |||
| e2bf42e66b | |||
| 0c72ca9294 | |||
| 2985fad77c | |||
| 02b5fb4d0e | |||
| bf417c163c | |||
| b35974e455 | |||
| 6d0abf865e | |||
| 275af9be82 | |||
| f4e44a1975 | |||
| 81f322b616 | |||
| f094ef57ec | |||
| 2e32d8f6e5 | |||
| 3e352f270d | |||
| 45056e8ff4 | |||
| b13abe51bf | |||
| c3513427de | |||
| 7a6b6882d2 | |||
| d6ec34cef9 | |||
| 84dfdd707a | |||
| 517a239485 | |||
| 47868051f8 | |||
| 96e4e9df66 | |||
| 7d510e4028 | |||
| 6760b29148 | |||
| 122063b1d5 | |||
| b304c3a175 | |||
| 5b89d73c20 | |||
| 8380dda25a | |||
| 7839116134 | |||
| b3a809ab1c | |||
| 3a0e58c3da | |||
| 26433c9020 | |||
| 6dbf84f401 | |||
| 3220ff728f | |||
| d8d1942673 | |||
| 8e329b2dd2 | |||
| 3622f8cad7 | |||
| 0513763607 | |||
| b7e3ea9e3d | |||
| 3ea2cd14d1 | |||
| 7b7875991f | |||
| b1a106d4d8 | |||
| 0281d86f1a | |||
| 2231156873 | |||
| ecc8930bec | |||
| 5814740a5d | |||
| 25159c760a | |||
| 3ff9132acb | |||
| b5f00f254c | |||
| 70f2c473d5 | |||
| b3b11d726d | |||
| f97d5bc731 | |||
| 49507d06c7 | |||
| 5d928c486f | |||
| 0485e9d64c | |||
| cc0839204e | |||
| 760a85a1da | |||
| c821774e9b | |||
| 47a19a7e77 | |||
| a75f1abd71 | |||
| 09c497ff96 | |||
| cae1d9de02 | |||
| 1050a4f6a7 | |||
| be4ef44c13 | |||
| 89e4132fc1 | |||
| 8d8201822b | |||
| 726eb4632e | |||
| ffcb2ee608 | |||
| 24f8be6e80 | |||
| 08fa4aefc4 | |||
| 13bbd5dfc1 | |||
| 8e6eeab680 | |||
| 70d9d5063a | |||
| 374429f161 | |||
| c69666e747 | |||
| 7dc04b4a07 | |||
| 7b5e54aaba | |||
| 30b704c90f | |||
| 2f98b5afaa | |||
| 3c3b43cfc5 | |||
| 09f2a534be | |||
| 7b5b673ebf | |||
| c72d0a83ca | |||
| 3159289ac0 | |||
| a9cc5fac73 | |||
| fe06fccacd | |||
| 8b4a46f7eb | |||
| cf362caaf2 | |||
| de1be7d296 | |||
| d8e3e1a72f | |||
| 64a7ad844f | |||
| 9201c4ca96 | |||
| dab6b6f723 | |||
| 495243d177 | |||
| 332f07c93d | |||
| 54d4be9762 | |||
| f1e3c29c97 | |||
| 66d393a465 | |||
| 218d3392f0 | |||
| 0136d91cc3 | |||
| a95f0350d8 | |||
| 55c04b6585 | |||
| ea21bc362a | |||
| 117d92b879 | |||
| 440c8e4618 | |||
| 1344526f7f | |||
| 19acfbc76f | |||
| 9dfb27f0a4 | |||
| 51cd830710 | |||
| 956ba2ad46 | |||
| 3ae3107760 | |||
| 925d4b8bcf | |||
| ca6dbfd12d | |||
| 9ea03d0c6d | |||
| 6ad4929d53 | |||
| 446f419af0 | |||
| f3c5de82e0 | |||
| 56e24752cf | |||
| 255af13b20 | |||
| 02b4f1eb43 | |||
| 8c735d3921 | |||
| 70e6038215 | |||
| fc7501c4fe | |||
| 45b60cfea1 | |||
| 09313ad471 | |||
| 1b15aecbff | |||
| 2bea7dbc8d | |||
| 3468b5f236 | |||
| 1c431d14dc | |||
| 7234a70265 | |||
| a459d84b00 | |||
| 49d2ed8244 | |||
| d6aebfcb99 | |||
| 2085eb7869 | |||
| c101a86f02 | |||
| 2d32769a59 | |||
| a2f755388e | |||
| 8a8f1af2bd | |||
| 4582b8c5b9 | |||
| f66fbf6656 | |||
| 41d49ccce5 | |||
| c85f450742 | |||
| e314dae10d | |||
| b1192a1912 | |||
| 7cc8a946fd | |||
| 4b34852c72 | |||
| 5d7fc9dabd | |||
| db61952e67 | |||
| 016dca242c | |||
| 983811af97 | |||
| d18a9726ac | |||
| cdef838d3e | |||
| 7703d724e1 | |||
| 94b5efbd00 | |||
| f43020b864 | |||
| 0d0f808305 | |||
| 279e8b15e0 | |||
| 099f729303 | |||
| 5150a31cdb | |||
| b5d17dc862 | |||
| e6c5feb3f3 | |||
| 5573e941c6 | |||
| 29dbca20e0 |
2
.gitignore
vendored
@@ -1,3 +1,5 @@
|
|||||||
.bundle
|
.bundle
|
||||||
.config
|
.config
|
||||||
|
.dockerrc
|
||||||
|
.vscode
|
||||||
Gemfile.lock
|
Gemfile.lock
|
||||||
|
|||||||
3
Gemfile
@@ -1,14 +1,13 @@
|
|||||||
source 'https://rubygems.org'
|
source 'https://rubygems.org'
|
||||||
|
|
||||||
gem 'quickbooks-ruby'
|
gem 'quickbooks-ruby'
|
||||||
gem 'quickbooks-ruby-base'
|
|
||||||
gem 'oauth-plugin'
|
|
||||||
gem 'oauth2'
|
gem 'oauth2'
|
||||||
gem 'roxml'
|
gem 'roxml'
|
||||||
gem 'nhtsa_vin'
|
gem 'nhtsa_vin'
|
||||||
gem 'will_paginate'
|
gem 'will_paginate'
|
||||||
gem 'rails-jquery-autocomplete'
|
gem 'rails-jquery-autocomplete'
|
||||||
gem 'jquery-ui-rails'
|
gem 'jquery-ui-rails'
|
||||||
|
gem 'rexml'
|
||||||
|
|
||||||
group :assets do
|
group :assets do
|
||||||
gem 'coffee-rails'
|
gem 'coffee-rails'
|
||||||
|
|||||||
2
LICENSE
@@ -1,6 +1,6 @@
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (c) 2018 Rick Barrette
|
Copyright (c) 2016 - 2024 Rick Barrette
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
67
README.md
@@ -2,48 +2,51 @@
|
|||||||
|
|
||||||
A plugin for Redmine to connect to Quickbooks Online
|
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.
|
The goal of this project is to allow Redmine to connect with Quickbooks Online to create Time Activity Entries for billable hours loged when an Issue is closed.
|
||||||
|
|
||||||
#### Disclaimer
|
#### Disclaimer
|
||||||
|
|
||||||
OAuth2 is hacked into place with version 0.8.0 & working but I'm sure I missed a few things
|
Note: Although the core functionality is complete, this project is still under development & the master branch may be unstable. Tags should be stable and are recommended
|
||||||
|
|
||||||
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
|
Use tags for the following Redmine Versions
|
||||||
|
* Version 2.0.0+ for Redmine 5+
|
||||||
Also worth metioning I am currently using this in a live production enviroment with no issues
|
* Version 1.0.0+ for Redmine 4+
|
||||||
|
* Version 0.8.1 for Redine 3
|
||||||
|
|
||||||
#### Features
|
#### Features
|
||||||
* Issues can be assigned to a `Customer` via drop down in the edit Issue form
|
* Issues can be assigned to a Customer via drop down in the edit Issue form
|
||||||
* The `Employee` for the Issue is assigned via the assigned Redmine User
|
- Once a customer is attached to an Issue, you can attach an Estimate to the issue via a drop down menu
|
||||||
- This is set via a drop down in the user admistration page.
|
* Employee is assigned to a user via a drop down in the user admistration page.
|
||||||
* IF an `Issue` has been assined a `Customer` when an Issue is closed the following will happen:
|
* IF an Issue has been assined a Customer when an Issue is closed the following will happen:
|
||||||
- A new `Time Activity` will be billed agaist the `Customer` assinged to the issue for each Redmine Time Entery.
|
- A new Time Activity will be billed agaist the Customer assinged to the issue for each Redmine Time Entery.
|
||||||
+ Time Entries will be totalled up by Activity name. This will allow billing for diffrent activities without having to create seperate Issues.
|
+ Time Entries will be totalled up by Activity name. This will allow billing for diffrent activities without having to create seperate Issues.
|
||||||
+ The Time Activity names are used to lookup `Items` in Quickbooks.
|
+ The Time Activity names are used to dynamically lookup Items in Quickbooks.
|
||||||
+ IF there isn'tany Items that match the Activity name it will be skipped, and will not be billed to the `Customer`
|
+ IF there isn't any Items that match the Activity name it will be skipped, and will not be billed to the Customer
|
||||||
- Labor Rates are set by the `Item` in Quickbooks
|
- Labor Rates are set by corresponding the Item in Quickbooks
|
||||||
* `Payments` Can be created via the Redmine application menu
|
* Customers Can be created via the New Customer Page
|
||||||
* `Customers` Can be created via the Redmine application menu
|
- Customers can be searched by name or phone number
|
||||||
- `Customers` can be searched
|
- Basic information for the Customer can be viewed/edit via the Customer page
|
||||||
- Basic information for the `Customer` can be viewed/edit via the Customer page
|
|
||||||
* Webhook Support
|
* Webhook Support
|
||||||
- `Invoices` are automaticly attached to an Issue if a line item has a hashtag number in a `Line Item`
|
- Invoices are automaticly attached to an Issue if a line item has a hashtag number in a Line Item
|
||||||
+ `Invoice` Custom Fields are matched Issue Custom Fileds and are automaticly updated in Quickbooks. For example, this is usefull for extracting the Mileage In / Out from the Issue and updating the Invoice with the information.
|
+ Invoice Custom Fields are matched Issue Custom Fileds and are automaticly updated in Quickbooks. For example, this is usefull for extracting the Mileage In / Out from the Issue and updating the Invoice with the information.
|
||||||
- `Customers` are automaticly updated in local database
|
- Customers are automaticly updated in local database
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
* Sign up to become a developer for Intuit https://developer.intuit.com/
|
* Sign up to become a developer for Intuit https://developer.intuit.com/
|
||||||
* Create your own aplication to obtain your API keys
|
* Create your own aplication to obtain your API keys
|
||||||
* Set up webhook service to https://redmine.yourdomain.com/qbo/webhook
|
* Set up webhook service to https://redmine.yourdomain.com/qbo/webhook
|
||||||
- See https://developer.intuit.com/docs/0100_accounting/0300_developer_guides/webhooks
|
|
||||||
|
|
||||||
## The Install
|
## The Install
|
||||||
|
|
||||||
1. To install, clone this repo into your plugin folder
|
1. To install, clone this repo into your plugin folder & checkout a tagged version
|
||||||
|
|
||||||
`git clone git@github.com:rickbarrette/redmine_qbo.git`
|
`git clone git@github.com:rickbarrette/redmine_qbo.git`
|
||||||
|
|
||||||
|
then
|
||||||
|
|
||||||
|
`git checkout <tag>`
|
||||||
|
|
||||||
2. Migrate your database
|
2. Migrate your database
|
||||||
|
|
||||||
`rake redmine:plugins:migrate RAILS_ENV=production`
|
`rake redmine:plugins:migrate RAILS_ENV=production`
|
||||||
@@ -54,34 +57,22 @@ Also worth metioning I am currently using this in a live production enviroment w
|
|||||||
|
|
||||||
5. Assign an Employee to each of your users via the User Administration Page
|
5. Assign an Employee to each of your users via the User Administration Page
|
||||||
|
|
||||||
## Automatic Deploy
|
|
||||||
|
|
||||||
If you want the redmine server to be automaticly restarted after a git pull event add this hook to your git hook directory
|
|
||||||
https://gist.github.com/rickbarrette/3c999c7f37e321f9c60380de99e494f5
|
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
To enable automatic `Time Activity` entries for an Issue , you need only to assign a `Customer` to an Issue via drop downs in the issue creation/update form.
|
To enable automatic Time Activity entries for an Issue , you need only to assign a Customer to an Issue via drop downs in the issue creation/update form.
|
||||||
|
|
||||||
Note: After the inital synchronization, this plugin will recieve push notifications via Intuit's webhook service.
|
Note: After the inital synchronization, this plugin will recieve push notifications via Intuit's webhook service.
|
||||||
|
|
||||||
## TODO
|
## TODO
|
||||||
* Abiltiy to add line items to a ticket in a dynamic table so they can be added to the invoice upon closing of the issue
|
|
||||||
* Customer Deletion
|
|
||||||
* Email Customer updates, provding a link that would: bypass the login page, go directly to the issue directing them to, and allow them to view only that issue.
|
|
||||||
* Add Setting for Sandbox Mode
|
* Add Setting for Sandbox Mode
|
||||||
* Refactor Models prefixed with Qbo...
|
* Seperate Vehicles into a seperate plugin (I use redmine for my automotive shop management 😉)
|
||||||
* Seperate Vehicles into a seperate plugin
|
* MORE Stuff as I make it up...
|
||||||
* Make HTML Pretty
|
|
||||||
* Intergrate Customer Search into Redmine Search
|
|
||||||
* Fix Issue sort by Customer
|
|
||||||
* MORE Stuff...
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (c) 2020 rick barrette
|
Copyright (c) 2016 - 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:
|
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:
|
||||||
|
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 346 KiB |
BIN
Screenshots/plugin_cusomer_search.png
Normal file
|
After Width: | Height: | Size: 148 KiB |
BIN
Screenshots/plugin_customer_detail.png
Normal file
|
After Width: | Height: | Size: 303 KiB |
|
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 240 KiB |
|
Before Width: | Height: | Size: 106 KiB After Width: | Height: | Size: 512 KiB |
|
Before Width: | Height: | Size: 49 KiB |
@@ -1,6 +1,6 @@
|
|||||||
#The MIT License (MIT)
|
#The MIT License (MIT)
|
||||||
#
|
#
|
||||||
#Copyright (c) 2017 rick barrette
|
#Copyright (c) 2024 rick barrette
|
||||||
#
|
#
|
||||||
#Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
#Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
#
|
#
|
||||||
@@ -10,7 +10,6 @@
|
|||||||
|
|
||||||
# This controller class will handle map management
|
# This controller class will handle map management
|
||||||
class CustomersController < ApplicationController
|
class CustomersController < ApplicationController
|
||||||
unloadable
|
|
||||||
|
|
||||||
include AuthHelper
|
include AuthHelper
|
||||||
helper :issues
|
helper :issues
|
||||||
@@ -27,24 +26,34 @@ class CustomersController < ApplicationController
|
|||||||
include SortHelper
|
include SortHelper
|
||||||
helper :timelog
|
helper :timelog
|
||||||
|
|
||||||
before_filter :add_customer, :only => :new
|
before_action :add_customer, :only => :new
|
||||||
before_filter :view_customer, :except => :new
|
before_action :view_customer, :except => [:new, :view]
|
||||||
skip_before_filter :verify_authenticity_token, :check_if_login_required, :only => [:view]
|
skip_before_action :verify_authenticity_token, :check_if_login_required, :only => [:view]
|
||||||
|
|
||||||
default_search_scope :names
|
default_search_scope :names
|
||||||
|
|
||||||
autocomplete :customer, :name, :full => true, :extra_data => [:id]
|
autocomplete :customer, :name, :full => true, :extra_data => [:id]
|
||||||
|
|
||||||
|
def allowed_params
|
||||||
|
params.require(:customer).permit(:name, :email, :primary_phone, :mobile_phone, :phone_number, :notes)
|
||||||
|
end
|
||||||
|
|
||||||
|
# getter method for a customer's vehicles
|
||||||
|
# used for customer autocomplete field / issue form
|
||||||
def filter_vehicles_by_customer
|
def filter_vehicles_by_customer
|
||||||
@filtered_vehicles = Vehicle.all.where(customer_id: params[:selected_customer])
|
@filtered_vehicles = Vehicle.all.where(customer_id: params[:selected_customer])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# getter method for a customer's invoices
|
||||||
|
# used for customer autocomplete field / issue form
|
||||||
def filter_invoices_by_customer
|
def filter_invoices_by_customer
|
||||||
@filtered_invoices = QboInvoice.all.where(customer_id: params[:selected_customer])
|
@filtered_invoices = Invoice.all.where(customer_id: params[:selected_customer])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# getter method for a customer's estimates
|
||||||
|
# used for customer autocomplete field / issue form
|
||||||
def filter_estimates_by_customer
|
def filter_estimates_by_customer
|
||||||
@filtered_estimates = QboEstimate.all.where(customer_id: params[:selected_customer])
|
@filtered_estimates = Estimate.all.where(customer_id: params[:selected_customer])
|
||||||
end
|
end
|
||||||
|
|
||||||
# display a list of all customers
|
# display a list of all customers
|
||||||
@@ -57,12 +66,14 @@ class CustomersController < ApplicationController
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# initialize a new customer
|
||||||
def new
|
def new
|
||||||
@customer = Customer.new
|
@customer = Customer.new
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# create a new customer
|
||||||
def create
|
def create
|
||||||
@customer = Customer.new(params[:customer])
|
@customer = Customer.new(allowed_params)
|
||||||
if @customer.save
|
if @customer.save
|
||||||
flash[:notice] = "New Customer Created"
|
flash[:notice] = "New Customer Created"
|
||||||
redirect_to @customer
|
redirect_to @customer
|
||||||
@@ -77,8 +88,15 @@ class CustomersController < ApplicationController
|
|||||||
begin
|
begin
|
||||||
@customer = Customer.find_by_id(params[:id])
|
@customer = Customer.find_by_id(params[:id])
|
||||||
@vehicles = @customer.vehicles.paginate(:page => params[:page])
|
@vehicles = @customer.vehicles.paginate(:page => params[:page])
|
||||||
@issues = @customer.issues
|
@issues = @customer.issues.order(id: :desc)
|
||||||
rescue ActiveRecord::RecordNotFound
|
@billing_address = address_to_s(@customer.billing_address)
|
||||||
|
@shipping_address = address_to_s(@customer.shipping_address)
|
||||||
|
@closed_issues = (@issues - @issues.open)
|
||||||
|
@hours = 0
|
||||||
|
@closed_hours = 0
|
||||||
|
@issues.open.each { |i| @hours+= i.total_spent_hours }
|
||||||
|
@closed_issues.each { |i| @closed_hours+= i.total_spent_hours }
|
||||||
|
rescue
|
||||||
render_404
|
render_404
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -87,7 +105,7 @@ class CustomersController < ApplicationController
|
|||||||
def edit
|
def edit
|
||||||
begin
|
begin
|
||||||
@customer = Customer.find_by_id(params[:id])
|
@customer = Customer.find_by_id(params[:id])
|
||||||
rescue ActiveRecord::RecordNotFound
|
rescue
|
||||||
render_404
|
render_404
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -96,42 +114,62 @@ class CustomersController < ApplicationController
|
|||||||
def update
|
def update
|
||||||
begin
|
begin
|
||||||
@customer = Customer.find_by_id(params[:id])
|
@customer = Customer.find_by_id(params[:id])
|
||||||
if @customer.update_attributes(params[:customer])
|
if @customer.update(allowed_params)
|
||||||
flash[:notice] = "Customer updated"
|
flash[:notice] = "Customer updated"
|
||||||
redirect_to @customer
|
redirect_to @customer
|
||||||
else
|
else
|
||||||
redirect_to edit_customer_path
|
redirect_to edit_customer_path
|
||||||
flash[:error] = @customer.errors.full_messages.to_sentence if @customer.errors
|
flash[:error] = @customer.errors.full_messages.to_sentence if @customer.errors
|
||||||
end
|
end
|
||||||
rescue ActiveRecord::RecordNotFound
|
rescue
|
||||||
render_404
|
render_404
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# delete a customer
|
||||||
def destroy
|
def destroy
|
||||||
begin
|
begin
|
||||||
Customer.find_by_id(params[:id]).destroy
|
Customer.find_by_id(params[:id]).destroy
|
||||||
flash[:notice] = "Customer deleted successfully"
|
flash[:notice] = "Customer deleted successfully"
|
||||||
redirect_to action: :index
|
redirect_to action: :index
|
||||||
rescue ActiveRecord::RecordNotFound
|
rescue
|
||||||
render_404
|
render_404
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Customer view for an issue
|
# creates new customer view tokens, removes expired tokens & redirects to newly created customer view with new token.
|
||||||
|
def share
|
||||||
|
|
||||||
|
Thread.new do
|
||||||
|
logger.info "Removing expired customer tokens"
|
||||||
|
CustomerToken.remove_expired_tokens
|
||||||
|
ActiveRecord::Base.connection.close
|
||||||
|
end
|
||||||
|
|
||||||
|
begin
|
||||||
|
issue = Issue.find_by_id(params[:id])
|
||||||
|
redirect_to view_path issue.share_token.token
|
||||||
|
rescue
|
||||||
|
render_404
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# displays an issue for a customer with a provided security CustomerToken
|
||||||
def view
|
def view
|
||||||
|
|
||||||
User.current = User.find_by lastname: 'Anonymous'
|
User.current = User.find_by lastname: 'Anonymous'
|
||||||
|
|
||||||
@token = CustomerToken.where("token = ? and expires_at > ?", params[:token], Time.now)
|
@token = CustomerToken.find_by token: params[:token]
|
||||||
@token = @token.first
|
begin
|
||||||
if @token
|
@token.destroy if @token.expired?
|
||||||
|
raise "Token Expired" if @token.destroyed
|
||||||
|
|
||||||
session[:token] = @token.token
|
session[:token] = @token.token
|
||||||
@issue = Issue.find @token.issue_id
|
@issue = Issue.find @token.issue_id
|
||||||
@journals = @issue.journals.
|
@journals = @issue.journals.
|
||||||
preload(:details).
|
preload(:details).
|
||||||
preload(:user => :email_address).
|
preload(:user => :email_address).
|
||||||
reorder(:created_on, :id).to_a
|
reorder(:created_on, :id).to_a
|
||||||
@journals.each_with_index {|j,i| j.indice = i+1}
|
@journals.each_with_index {|j,i| j.indice = i+1}
|
||||||
@journals.reject!(&:private_notes?) unless User.current.allowed_to?(:view_private_notes, @issue.project)
|
@journals.reject!(&:private_notes?) unless User.current.allowed_to?(:view_private_notes, @issue.project)
|
||||||
Journal.preload_journals_details_custom_fields(@journals)
|
Journal.preload_journals_details_custom_fields(@journals)
|
||||||
@@ -146,21 +184,25 @@ class CustomersController < ApplicationController
|
|||||||
@priorities = IssuePriority.active
|
@priorities = IssuePriority.active
|
||||||
@time_entry = TimeEntry.new(:issue => @issue, :project => @issue.project)
|
@time_entry = TimeEntry.new(:issue => @issue, :project => @issue.project)
|
||||||
@relation = IssueRelation.new
|
@relation = IssueRelation.new
|
||||||
else
|
rescue
|
||||||
render_403
|
render_403
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
# redmine permission - add customers
|
||||||
def add_customer
|
def add_customer
|
||||||
global_check_permission(:add_customers)
|
global_check_permission(:add_customers)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# redmine permission - view customers
|
||||||
def view_customer
|
def view_customer
|
||||||
global_check_permission(:view_customers)
|
global_check_permission(:view_customers)
|
||||||
end
|
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 )
|
def only_one_non_zero?( array )
|
||||||
found_non_zero = false
|
found_non_zero = false
|
||||||
array.each do |val|
|
array.each do |val|
|
||||||
@@ -172,4 +214,18 @@ class CustomersController < ApplicationController
|
|||||||
found_non_zero
|
found_non_zero
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# format a quickbooks address to a human readable string
|
||||||
|
def address_to_s (address)
|
||||||
|
return if address.nil?
|
||||||
|
string = address.line1 if address.line1
|
||||||
|
string << "\n" + address.line2 if address.line2
|
||||||
|
string << "\n" + address.line3 if address.line3
|
||||||
|
string << "\n" + address.line4 if address.line4
|
||||||
|
string << "\n" + address.line5 if address.line5
|
||||||
|
string << " " + address.city if address.city
|
||||||
|
string << ", " + address.country_sub_division_code if address.country_sub_division_code
|
||||||
|
string << " " + address.postal_code if address.postal_code
|
||||||
|
return string
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#The MIT License (MIT)
|
#The MIT License (MIT)
|
||||||
#
|
#
|
||||||
#Copyright (c) 2017 rick barrette
|
#Copyright (c) 2024 rick barrette
|
||||||
#
|
#
|
||||||
#Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
#Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
#
|
#
|
||||||
@@ -8,20 +8,51 @@
|
|||||||
#
|
#
|
||||||
#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.
|
#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 EstimateController < ApplicationController
|
class EstimateController < ApplicationController
|
||||||
unloadable
|
|
||||||
|
|
||||||
include AuthHelper
|
include AuthHelper
|
||||||
|
|
||||||
before_filter :require_user
|
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? }
|
||||||
|
|
||||||
|
def get_estimate
|
||||||
|
# Force sync for estimate by doc number if not found
|
||||||
|
if Estimate.find_by_doc_number(params[:search]).nil?
|
||||||
|
begin
|
||||||
|
Estimate.sync_by_doc_number(params[:search]) if params[:search]
|
||||||
|
rescue
|
||||||
|
logger.info "Estimate.find_by_doc_number failed"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
estimate = Estimate.find_by_id(params[:id]) if params[:id]
|
||||||
|
estimate = Estimate.find_by_doc_number(params[:search]) if params[:search]
|
||||||
|
return estimate
|
||||||
|
end
|
||||||
|
|
||||||
#
|
#
|
||||||
# Downloads and forwards the estimate pdf
|
# Downloads and forwards the estimate pdf
|
||||||
#
|
#
|
||||||
def show
|
def show
|
||||||
base = QboEstimate.get_base
|
estimate = get_estimate
|
||||||
estimate = base.fetch_by_id(params[:id])
|
|
||||||
@pdf = base.pdf(estimate)
|
begin
|
||||||
send_data @pdf, filename: "estimate #{estimate.doc_number}.pdf", :disposition => 'inline', :type => "application/pdf"
|
send_data estimate.pdf, filename: "estimate #{estimate.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
|
||||||
|
estimate = get_estimate
|
||||||
|
|
||||||
|
begin
|
||||||
|
send_data estimate.pdf, filename: "estimate #{estimate.doc_number}.pdf", :disposition => 'inline', :type => "application/pdf"
|
||||||
|
rescue
|
||||||
|
redirect_to :back, :flash => { :error => "Estimate not found" }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#The MIT License (MIT)
|
#The MIT License (MIT)
|
||||||
#
|
#
|
||||||
#Copyright (c) 2017 rick barrette
|
#Copyright (c) 2024 rick barrette
|
||||||
#
|
#
|
||||||
#Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
#Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
#
|
#
|
||||||
@@ -8,20 +8,26 @@
|
|||||||
#
|
#
|
||||||
#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.
|
#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 InvoiceController < ApplicationController
|
class InvoiceController < ApplicationController
|
||||||
unloadable
|
|
||||||
|
|
||||||
include AuthHelper
|
include AuthHelper
|
||||||
|
|
||||||
before_filter :require_user, :unless => proc {|c| session[:token].nil? }
|
before_action :require_user, :unless => proc {|c| session[:token].nil? }
|
||||||
skip_before_filter :verify_authenticity_token, :check_if_login_required, :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
|
# Downloads and forwards the invoice pdf
|
||||||
#
|
#
|
||||||
def show
|
def show
|
||||||
base = QboInvoice.get_base
|
begin
|
||||||
invoice = base.fetch_by_id(params[:id])
|
qbo = Qbo.first
|
||||||
@pdf = base.pdf(invoice)
|
qbo.perform_authenticated_request do |access_token|
|
||||||
send_data @pdf, filename: "invoice #{invoice.doc_number}.pdf", :disposition => 'inline', :type => "application/pdf"
|
service = Quickbooks::Service::Invoice.new(:company_id => qbo.realm_id, :access_token => access_token)
|
||||||
|
invoice = service.fetch_by_id(params[:id])
|
||||||
|
@pdf = service.pdf(invoice)
|
||||||
|
send_data @pdf, filename: "invoice #{invoice.doc_number}.pdf", :disposition => 'inline', :type => "application/pdf"
|
||||||
|
end
|
||||||
|
rescue
|
||||||
|
redirect_to :back, :flash => { :error => "Invoice not found" }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,94 +0,0 @@
|
|||||||
#The MIT License (MIT)
|
|
||||||
#
|
|
||||||
#Copyright (c) 2018 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.
|
|
||||||
|
|
||||||
# This controller class will handle map management
|
|
||||||
class LineItemsController < ApplicationController
|
|
||||||
unloadable
|
|
||||||
|
|
||||||
include AuthHelper
|
|
||||||
|
|
||||||
before_filter :require_user
|
|
||||||
|
|
||||||
# display all line items for an issue
|
|
||||||
def index
|
|
||||||
if params[:issue_id]
|
|
||||||
begin
|
|
||||||
@line_items = Issue.find_by_id(params[:issue_id]).line_items
|
|
||||||
rescue ActiveRecord::RecordNotFound
|
|
||||||
render_404
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# return an HTML form for creating a new line item
|
|
||||||
def new
|
|
||||||
@line_item = LineItem.new
|
|
||||||
end
|
|
||||||
|
|
||||||
# create a new line item
|
|
||||||
def create
|
|
||||||
@line_item = LineItem.new(params[:line_item])
|
|
||||||
if @line_item.save
|
|
||||||
flash[:notice] = "New Line Item Created"
|
|
||||||
redirect_to @line_item.issue
|
|
||||||
else
|
|
||||||
flash[:error] = @line_item.errors.full_messages.to_sentence
|
|
||||||
redirect_to new_line_item_path
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# display a specific line item
|
|
||||||
def show
|
|
||||||
begin
|
|
||||||
@line_item = LineItem.find_by_id(params[:id])
|
|
||||||
rescue ActiveRecord::RecordNotFound
|
|
||||||
render_404
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# return an HTML form for editing a line item
|
|
||||||
def edit
|
|
||||||
begin
|
|
||||||
@line_item = LineItem.find_by_id(params[:id])
|
|
||||||
rescue ActiveRecord::RecordNotFound
|
|
||||||
render_404
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# update a specific line item
|
|
||||||
def update
|
|
||||||
begin
|
|
||||||
@line_item = LineItem.find_by_id(params[:id])
|
|
||||||
if @line_item.update_attributes(params[:line_item])
|
|
||||||
flash[:notice] = "Line Item updated"
|
|
||||||
redirect_to @line_item
|
|
||||||
else
|
|
||||||
flash[:error] = @line_item.errors.full_messages.to_sentence if @line_item.errors
|
|
||||||
redirect_to edit_line_item_path
|
|
||||||
end
|
|
||||||
rescue ActiveRecord::RecordNotFound
|
|
||||||
render_404
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# delete a specific line item
|
|
||||||
def destroy
|
|
||||||
begin
|
|
||||||
line_item = LineItem.find_by_id(params[:id])
|
|
||||||
issue = line_item.issue
|
|
||||||
line_item.destroy
|
|
||||||
flash[:notice] = "Line Item deleted successfully"
|
|
||||||
redirect_to issue
|
|
||||||
rescue ActiveRecord::RecordNotFound
|
|
||||||
render_404
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
#The MIT License (MIT)
|
|
||||||
#
|
|
||||||
#Copyright (c) 2017 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 PaymentsController < ApplicationController
|
|
||||||
unloadable
|
|
||||||
|
|
||||||
include AuthHelper
|
|
||||||
|
|
||||||
before_filter :check_permissions
|
|
||||||
|
|
||||||
def new
|
|
||||||
@payment = Payment.new
|
|
||||||
|
|
||||||
@customers = Customer.all.sort_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).all
|
|
||||||
end
|
|
||||||
|
|
||||||
def create
|
|
||||||
@payment = Payment.new(params[:payment])
|
|
||||||
if @payment.save
|
|
||||||
flash[:notice] = "Payment Saved"
|
|
||||||
redirect_to Customer.find_by_id(@payment.customer_id)
|
|
||||||
else
|
|
||||||
flash[:error] = @payment.errors.full_messages.to_sentence
|
|
||||||
redirect_to new_customer_path
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def check_permissions
|
|
||||||
if !allowed_to?(:add_payments)
|
|
||||||
render :file => "public/401.html.erb", :status => :unauthorized, :layout =>true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def only_one_non_zero?( array )
|
|
||||||
found_non_zero = false
|
|
||||||
array.each do |val|
|
|
||||||
if val!=0
|
|
||||||
return false if found_non_zero
|
|
||||||
found_non_zero = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
found_non_zero
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
#The MIT License (MIT)
|
#The MIT License (MIT)
|
||||||
#
|
#
|
||||||
#Copyright (c) 2020 rick barrette
|
#Copyright (c) 2016 - 2025 rick barrette
|
||||||
#
|
#
|
||||||
#Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
#Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
#
|
#
|
||||||
@@ -9,35 +9,26 @@
|
|||||||
#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.
|
#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 QboController < ApplicationController
|
class QboController < ApplicationController
|
||||||
unloadable
|
|
||||||
|
|
||||||
require 'openssl'
|
require 'openssl'
|
||||||
|
|
||||||
include AuthHelper
|
include AuthHelper
|
||||||
|
|
||||||
before_filter :require_user, :except => :qbo_webhook
|
before_action :require_user, :except => :webhook
|
||||||
skip_before_filter :verify_authenticity_token, :check_if_login_required, :only => [:qbo_webhook]
|
skip_before_action :verify_authenticity_token, :check_if_login_required, :only => [:webhook]
|
||||||
|
|
||||||
#
|
def allowed_params
|
||||||
# Called when the QBO Top Menu us shown
|
params.permit(:code, :state, :realmId, :id)
|
||||||
#
|
|
||||||
def index
|
|
||||||
@qbo = Qbo.first
|
|
||||||
@customer_count = Customer.count
|
|
||||||
@qbo_item_count = QboItem.count
|
|
||||||
@qbo_employee_count = QboEmployee.count
|
|
||||||
@qbo_invoice_count = QboInvoice.count
|
|
||||||
@qbo_estimate_count = QboEstimate.count
|
|
||||||
end
|
end
|
||||||
|
|
||||||
#
|
#
|
||||||
# Called when the user requests that Redmine to connect to QBO
|
# Called when the user requests that Redmine to connect to QBO
|
||||||
#
|
#
|
||||||
def authenticate
|
def authenticate
|
||||||
oauth2_client = Qbo.get_client
|
redirect_uri = "#{Setting.protocol}://#{Setting.host_name + qbo_oauth_callback_path}"
|
||||||
callback = "https://redmine.rickbarrette.org/qbo/oauth_callback/"
|
logger.info "redirect_uri: #{redirect_uri}"
|
||||||
#callback = qbo_oauth_callback_url
|
oauth2_client = Qbo.construct_oauth2_client
|
||||||
grant_url = oauth2_client.auth_code.authorize_url(redirect_uri: callback, response_type: "code", state: SecureRandom.hex(12), scope: "com.intuit.quickbooks.accounting")
|
grant_url = oauth2_client.auth_code.authorize_url(redirect_uri: redirect_uri, response_type: "code", state: SecureRandom.hex(12), scope: "com.intuit.quickbooks.accounting")
|
||||||
redirect_to grant_url
|
redirect_to grant_url
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -46,33 +37,23 @@ class QboController < ApplicationController
|
|||||||
#
|
#
|
||||||
def oauth_callback
|
def oauth_callback
|
||||||
if params[:state].present?
|
if params[:state].present?
|
||||||
oauth2_client = Qbo.get_client
|
oauth2_client = Qbo.construct_oauth2_client
|
||||||
# use the state value to retrieve from your backend any information you need to identify the customer in your system
|
# use the state value to retrieve from your backend any information you need to identify the customer in your system
|
||||||
#redirect_uri = qbo_oauth_callback_url
|
redirect_uri = "#{Setting.protocol}://#{Setting.host_name + qbo_oauth_callback_path}"
|
||||||
redirect_uri = "https://redmine.rickbarrette.org/qbo/oauth_callback/"
|
|
||||||
if resp = oauth2_client.auth_code.get_token(params[:code], redirect_uri: redirect_uri)
|
if resp = oauth2_client.auth_code.get_token(params[:code], redirect_uri: redirect_uri)
|
||||||
# save your tokens here. For example:
|
|
||||||
# quickbooks_credentials.update_attributes(access_token: resp.token, refresh_token: resp.refresh_token,
|
|
||||||
# realm_id: params[:realmId])
|
|
||||||
|
|
||||||
|
# Remove the last authentication information
|
||||||
Qbo.delete_all
|
Qbo.delete_all
|
||||||
|
|
||||||
# Save the authentication information
|
# Save the authentication information
|
||||||
qbo = Qbo.new
|
qbo = Qbo.new
|
||||||
qbo.qb_token = resp.token
|
qbo.update(oauth2_access_token: resp.token, oauth2_refresh_token: resp.refresh_token, realm_id: params[:realmId])
|
||||||
qbo.qb_secret = resp.refresh_token
|
qbo.refresh_token!
|
||||||
qbo.token_expires_at = 6.months.from_now.utc
|
|
||||||
qbo.reconnect_token_at = 3.months.from_now.utc
|
|
||||||
qbo.company_id = params[:realmId]
|
|
||||||
|
|
||||||
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!
|
if qbo.save!
|
||||||
redirect_to qbo_sync_path, :flash => { :notice => "Successfully connected to Quickbooks" }
|
redirect_to qbo_sync_path, :flash => { :notice => I18n.t(:label_connected) }
|
||||||
else
|
else
|
||||||
redirect_to plugin_settings_path(:redmine_qbo), :flash => { :error => "Error" }
|
redirect_to plugin_settings_path(:redmine_qbo), :flash => { :error => I18n.t(:label_error) }
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
@@ -84,14 +65,16 @@ class QboController < ApplicationController
|
|||||||
i = Issue.find_by_id params[:id]
|
i = Issue.find_by_id params[:id]
|
||||||
if i.customer
|
if i.customer
|
||||||
i.bill_time
|
i.bill_time
|
||||||
redirect_to i, :flash => { :notice => "Successfully Billed #{i.customer.name}" }
|
redirect_to i, :flash => { :notice => I18n.t(:label_billed_success) + i.customer.name }
|
||||||
else
|
else
|
||||||
redirect_to i, :flash => { :error => "Cannot bill without a customer assigned" }
|
redirect_to i, :flash => { :error => I18n.t(:label_billing_error) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Quickbooks Webhook Callback
|
# Quickbooks Webhook Callback
|
||||||
def qbo_webhook
|
def webhook
|
||||||
|
|
||||||
|
logger.info "Quickbooks is calling webhook"
|
||||||
|
|
||||||
# check the payload
|
# check the payload
|
||||||
signature = request.headers['intuit-signature']
|
signature = request.headers['intuit-signature']
|
||||||
@@ -101,58 +84,67 @@ class QboController < ApplicationController
|
|||||||
|
|
||||||
# proceed if the request is good
|
# proceed if the request is good
|
||||||
if hash.eql? signature
|
if hash.eql? signature
|
||||||
if request.headers['content-type'] == 'application/json'
|
Thread.new do
|
||||||
data = JSON.parse(data)
|
if request.headers['content-type'] == 'application/json'
|
||||||
else
|
data = JSON.parse(data)
|
||||||
# application/x-www-form-urlencoded
|
|
||||||
data = params.as_json
|
|
||||||
end
|
|
||||||
# Process the information
|
|
||||||
entities = data['eventNotifications'][0]['dataChangeEvent']['entities']
|
|
||||||
entities.each do |entity|
|
|
||||||
id = entity['id'].to_i
|
|
||||||
name = entity['name']
|
|
||||||
|
|
||||||
# TODO rename all other models!
|
|
||||||
name.prepend("Qbo") if not name.eql? "Customer"
|
|
||||||
|
|
||||||
# Magicly initialize the correct class
|
|
||||||
obj = name.constantize
|
|
||||||
|
|
||||||
# for merge events
|
|
||||||
obj.destroy(entity['deletedId']) if entity['deletedId']
|
|
||||||
|
|
||||||
#Check to see if we are deleting a record
|
|
||||||
if entity['operation'].eql? "Delete"
|
|
||||||
obj.destroy(id)
|
|
||||||
#if not then update!
|
|
||||||
else
|
else
|
||||||
obj.sync_by_id(id)
|
# application/x-www-form-urlencoded
|
||||||
|
data = params.as_json
|
||||||
end
|
end
|
||||||
|
# Process the information
|
||||||
|
entities = data['eventNotifications'][0]['dataChangeEvent']['entities']
|
||||||
|
entities.each do |entity|
|
||||||
|
id = entity['id'].to_i
|
||||||
|
name = entity['name']
|
||||||
|
|
||||||
|
logger.info "Casting #{name.constantize} to obj"
|
||||||
|
|
||||||
|
# Magicly initialize the correct class
|
||||||
|
obj = name.constantize
|
||||||
|
|
||||||
|
# for merge events
|
||||||
|
obj.destroy(entity['deletedId']) if entity['deletedId']
|
||||||
|
|
||||||
|
#Check to see if we are deleting a record
|
||||||
|
if entity['operation'].eql? "Delete"
|
||||||
|
obj.destroy(id)
|
||||||
|
#if not then update!
|
||||||
|
else
|
||||||
|
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
|
||||||
|
|
||||||
|
# Record that last time we updated
|
||||||
|
Qbo.update_time_stamp
|
||||||
|
ActiveRecord::Base.connection.close
|
||||||
end
|
end
|
||||||
|
|
||||||
# Record that last time we updated
|
|
||||||
Qbo.update_time_stamp
|
|
||||||
|
|
||||||
# The webhook doesn't require a response but let's make sure we don't send anything
|
# The webhook doesn't require a response but let's make sure we don't send anything
|
||||||
render :nothing => true
|
render :nothing => true, status: 200
|
||||||
else
|
else
|
||||||
render nothing: true, status: 400
|
render nothing: true, status: 400
|
||||||
end
|
end
|
||||||
|
|
||||||
|
logger.info "Quickbooks webhook complete"
|
||||||
end
|
end
|
||||||
|
|
||||||
#
|
#
|
||||||
# Synchronizes the QboCustomer table with QBO
|
# Synchronizes the QboCustomer table with QBO
|
||||||
#
|
#
|
||||||
def sync
|
def sync
|
||||||
|
logger.info "Syncing EVERYTHING"
|
||||||
# Update info in background
|
# Update info in background
|
||||||
Thread.new do
|
Thread.new do
|
||||||
if Qbo.exists?
|
if Qbo.exists?
|
||||||
Customer.sync
|
Customer.sync
|
||||||
QboInvoice.sync
|
Invoice.sync
|
||||||
QboItem.sync
|
Employee.sync
|
||||||
QboEmployee.sync
|
Estimate.sync
|
||||||
QboEstimate.sync
|
|
||||||
|
|
||||||
# Record the last sync time
|
# Record the last sync time
|
||||||
Qbo.update_time_stamp
|
Qbo.update_time_stamp
|
||||||
@@ -160,6 +152,6 @@ class QboController < ApplicationController
|
|||||||
ActiveRecord::Base.connection.close
|
ActiveRecord::Base.connection.close
|
||||||
end
|
end
|
||||||
|
|
||||||
redirect_to :home, :flash => { :notice => "Successfully synced to Quickbooks" }
|
redirect_to :home, :flash => { :notice => I18n.t(:label_syncing) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#The MIT License (MIT)
|
#The MIT License (MIT)
|
||||||
#
|
#
|
||||||
#Copyright (c) 2017 rick barrette
|
#Copyright (c) 2024 rick barrette
|
||||||
#
|
#
|
||||||
#Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
#Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
#
|
#
|
||||||
@@ -10,11 +10,14 @@
|
|||||||
|
|
||||||
# This controller class will handle map management
|
# This controller class will handle map management
|
||||||
class VehiclesController < ApplicationController
|
class VehiclesController < ApplicationController
|
||||||
unloadable
|
|
||||||
|
|
||||||
include AuthHelper
|
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
|
# display a list of all vehicles
|
||||||
def index
|
def index
|
||||||
@@ -26,6 +29,7 @@ class VehiclesController < ApplicationController
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# search for a vehicle by vin
|
||||||
if params[:search]
|
if params[:search]
|
||||||
@vehicles = Vehicle.search(params[:search]).paginate(:page => params[:page])
|
@vehicles = Vehicle.search(params[:search]).paginate(:page => params[:page])
|
||||||
if only_one_non_zero?(@vehicles)
|
if only_one_non_zero?(@vehicles)
|
||||||
@@ -42,7 +46,7 @@ class VehiclesController < ApplicationController
|
|||||||
|
|
||||||
# create a new vehicle
|
# create a new vehicle
|
||||||
def create
|
def create
|
||||||
@vehicle = Vehicle.new(params[:vehicle])
|
@vehicle = Vehicle.new(allowed_params)
|
||||||
if @vehicle.save
|
if @vehicle.save
|
||||||
flash[:notice] = "New Vehicle Created"
|
flash[:notice] = "New Vehicle Created"
|
||||||
redirect_to @vehicle
|
redirect_to @vehicle
|
||||||
@@ -57,7 +61,9 @@ class VehiclesController < ApplicationController
|
|||||||
begin
|
begin
|
||||||
@vehicle = Vehicle.find_by_id(params[:id])
|
@vehicle = Vehicle.find_by_id(params[:id])
|
||||||
@vin = @vehicle.vin.scan(/.{1,9}/) if @vehicle.vin
|
@vin = @vehicle.vin.scan(/.{1,9}/) if @vehicle.vin
|
||||||
rescue ActiveRecord::RecordNotFound
|
@issues = @vehicle.issues.order(id: :desc)
|
||||||
|
@closed_issues = (@issues - @issues.open)
|
||||||
|
rescue
|
||||||
render_404
|
render_404
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -67,7 +73,7 @@ class VehiclesController < ApplicationController
|
|||||||
begin
|
begin
|
||||||
@vehicle = Vehicle.find_by_id(params[:id])
|
@vehicle = Vehicle.find_by_id(params[:id])
|
||||||
@customer = @vehicle.customer
|
@customer = @vehicle.customer
|
||||||
rescue ActiveRecord::RecordNotFound
|
rescue
|
||||||
render_404
|
render_404
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -77,7 +83,7 @@ class VehiclesController < ApplicationController
|
|||||||
@customer = params[:customer]
|
@customer = params[:customer]
|
||||||
begin
|
begin
|
||||||
@vehicle = Vehicle.find_by_id(params[:id])
|
@vehicle = Vehicle.find_by_id(params[:id])
|
||||||
if @vehicle.update_attributes(params[:vehicle])
|
if @vehicle.update(allowed_params)
|
||||||
flash[:notice] = "Vehicle updated"
|
flash[:notice] = "Vehicle updated"
|
||||||
redirect_to @vehicle
|
redirect_to @vehicle
|
||||||
else
|
else
|
||||||
@@ -85,7 +91,7 @@ class VehiclesController < ApplicationController
|
|||||||
end
|
end
|
||||||
#show any errors anyways
|
#show any errors anyways
|
||||||
flash[:error] = @vehicle.errors.full_messages.to_sentence unless @vehicle.errors.empty?
|
flash[:error] = @vehicle.errors.full_messages.to_sentence unless @vehicle.errors.empty?
|
||||||
rescue ActiveRecord::RecordNotFound
|
rescue
|
||||||
render_404
|
render_404
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -96,13 +102,15 @@ class VehiclesController < ApplicationController
|
|||||||
Vehicle.find_by_id(params[:id]).destroy
|
Vehicle.find_by_id(params[:id]).destroy
|
||||||
flash[:notice] = "Vehicle deleted successfully"
|
flash[:notice] = "Vehicle deleted successfully"
|
||||||
redirect_to action: :index
|
redirect_to action: :index
|
||||||
rescue ActiveRecord::RecordNotFound
|
rescue
|
||||||
render_404
|
render_404
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
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 )
|
def only_one_non_zero?( array )
|
||||||
found_non_zero = false
|
found_non_zero = false
|
||||||
array.each do |val|
|
array.each do |val|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ module AuthHelper
|
|||||||
def require_user
|
def require_user
|
||||||
return unless session[:token].nil?
|
return unless session[:token].nil?
|
||||||
if !User.current.logged?
|
if !User.current.logged?
|
||||||
render :file => "public/401.html.erb", :status => :unauthorized, :layout =>true
|
render_403
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -27,14 +27,14 @@ module AuthHelper
|
|||||||
|
|
||||||
def check_permission(permission)
|
def check_permission(permission)
|
||||||
if !allowed_to?(permission)
|
if !allowed_to?(permission)
|
||||||
render :file => "public/401.html.erb", :status => :unauthorized, :layout =>true
|
render_403
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def global_check_permission(permission)
|
def global_check_permission(permission)
|
||||||
if !globaly_allowed_to?(permission)
|
if !globaly_allowed_to?(permission)
|
||||||
render :file => "public/401.html.erb", :status => :unauthorized, :layout =>true
|
render_403
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
84
app/models/concerns/quickbooks_oauth.rb
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
#The MIT License (MIT)
|
||||||
|
#
|
||||||
|
#Copyright (c) 2016 - 2025 rick barrette
|
||||||
|
#
|
||||||
|
#Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
#
|
||||||
|
#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.
|
||||||
|
|
||||||
|
module QuickbooksOauth
|
||||||
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
|
#== Instance Methods
|
||||||
|
|
||||||
|
def perform_authenticated_request(&block)
|
||||||
|
attempts = 0
|
||||||
|
begin
|
||||||
|
yield oauth_access_token
|
||||||
|
rescue OAuth2::Error, Quickbooks::AuthorizationFailure => ex
|
||||||
|
Rails.logger.error("QuickbooksOauth.perform: #{ex.message}")
|
||||||
|
|
||||||
|
# to prevent an infinite loop here keep a counter and bail out after N times...
|
||||||
|
attempts += 1
|
||||||
|
|
||||||
|
raise "QuickbooksOauth:ExceededAuthAttempts" if attempts >= 3
|
||||||
|
|
||||||
|
# check if its an invalid_grant first, but assume it is for now
|
||||||
|
refresh_token!
|
||||||
|
|
||||||
|
retry
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def refresh_token!
|
||||||
|
Rails.logger.info("QuickbooksOauth.refresh_token!")
|
||||||
|
t = oauth_access_token
|
||||||
|
refreshed = t.refresh!
|
||||||
|
|
||||||
|
if refreshed.params['x_refresh_token_expires_in'].to_i > 0
|
||||||
|
oauth2_refresh_token_expires_at = Time.now + refreshed.params['x_refresh_token_expires_in'].to_i.seconds
|
||||||
|
else
|
||||||
|
oauth2_refresh_token_expires_at = 100.days.from_now
|
||||||
|
end
|
||||||
|
|
||||||
|
Rails.logger.info("QuickbooksOauth.refresh_token!: #{oauth2_refresh_token_expires_at}")
|
||||||
|
|
||||||
|
update!(
|
||||||
|
oauth2_access_token: refreshed.token,
|
||||||
|
oauth2_access_token_expires_at: Time.at(refreshed.expires_at),
|
||||||
|
oauth2_refresh_token: refreshed.refresh_token,
|
||||||
|
oauth2_refresh_token_expires_at: oauth2_refresh_token_expires_at
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def oauth_client
|
||||||
|
self.class.construct_oauth2_client
|
||||||
|
end
|
||||||
|
|
||||||
|
def oauth_access_token
|
||||||
|
OAuth2::AccessToken.new(oauth_client, oauth2_access_token, refresh_token: oauth2_refresh_token)
|
||||||
|
end
|
||||||
|
|
||||||
|
def consumer
|
||||||
|
oauth_access_token
|
||||||
|
end
|
||||||
|
|
||||||
|
module ClassMethods
|
||||||
|
|
||||||
|
def construct_oauth2_client
|
||||||
|
|
||||||
|
oauth_consumer_key = Setting.plugin_redmine_qbo['settingsOAuthConsumerKey']
|
||||||
|
oauth_consumer_secret = Setting.plugin_redmine_qbo['settingsOAuthConsumerSecret']
|
||||||
|
|
||||||
|
options = {
|
||||||
|
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"
|
||||||
|
}
|
||||||
|
OAuth2::Client.new(oauth_consumer_key, oauth_consumer_secret, options)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
#The MIT License (MIT)
|
#The MIT License (MIT)
|
||||||
#
|
#
|
||||||
#Copyright (c) 2020 rick barrette
|
#Copyright (c) 2016 - 2025 rick barrette
|
||||||
#
|
#
|
||||||
#Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
#Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
#
|
#
|
||||||
@@ -9,22 +9,19 @@
|
|||||||
#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.
|
#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 Customer < ActiveRecord::Base
|
class Customer < ActiveRecord::Base
|
||||||
unloadable
|
|
||||||
|
|
||||||
has_many :issues
|
has_many :issues
|
||||||
has_many :qbo_purchases
|
has_many :invoices
|
||||||
has_many :qbo_invoices
|
has_many :estimates
|
||||||
has_many :qbo_estimates
|
|
||||||
has_many :vehicles
|
has_many :vehicles
|
||||||
|
|
||||||
attr_accessible :name, :notes, :email, :primary_phone, :mobile_phone, :phone_number
|
|
||||||
validates_presence_of :id, :name
|
validates_presence_of :id, :name
|
||||||
|
|
||||||
self.primary_key = :id
|
self.primary_key = :id
|
||||||
|
|
||||||
# returns a human readable string
|
# returns a human readable string
|
||||||
def to_s
|
def to_s
|
||||||
return name
|
return "#{self[:name]} - #{phone_number.split(//).last(4).join unless phone_number.nil?}"
|
||||||
end
|
end
|
||||||
|
|
||||||
# Convenience Method
|
# Convenience Method
|
||||||
@@ -89,6 +86,13 @@ class Customer < ActiveRecord::Base
|
|||||||
update_mobile_phone_number
|
update_mobile_phone_number
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Convenience Method
|
||||||
|
# Sets the notes
|
||||||
|
def notes=(s)
|
||||||
|
pull unless @details
|
||||||
|
@details.notes = s
|
||||||
|
end
|
||||||
|
|
||||||
# update the localy stored phone number as a plain string with no special chars
|
# update the localy stored phone number as a plain string with no special chars
|
||||||
def update_phone_number
|
def update_phone_number
|
||||||
begin
|
begin
|
||||||
@@ -136,29 +140,29 @@ class Customer < ActiveRecord::Base
|
|||||||
# proforms a bruteforce sync operation
|
# proforms a bruteforce sync operation
|
||||||
# This needs to be simplified
|
# This needs to be simplified
|
||||||
def self.sync
|
def self.sync
|
||||||
service = Qbo.get_base(:customer)
|
|
||||||
|
|
||||||
# Sync ALL customers if the database is empty
|
# Sync ALL customers if the database is empty
|
||||||
#if count == 0
|
qbo = Qbo.first
|
||||||
customers = service.all
|
customers = qbo.perform_authenticated_request do |access_token|
|
||||||
#else
|
service = Quickbooks::Service::Customer.new(:company_id => qbo.realm_id, :access_token => access_token)
|
||||||
# last = Qbo.first.last_sync
|
service.all
|
||||||
# query = "Select Id, DisplayName From Customer"
|
end
|
||||||
# query << " Where Metadata.LastUpdatedTime >= '#{last.iso8601}' " if last
|
|
||||||
# customers = service.query(query)
|
|
||||||
#end
|
|
||||||
|
|
||||||
customers.each do |customer|
|
return unless customers
|
||||||
qbo_customer = Customer.find_or_create_by(id: customer.id)
|
|
||||||
if customer.active?
|
customers.each do |c|
|
||||||
if not qbo_customer.name.eql? customer.display_name
|
logger.info "Processing customer #{c.id}"
|
||||||
qbo_customer.name = customer.display_name
|
customer = Customer.find_or_create_by(id: c.id)
|
||||||
qbo_customer.id = customer.id
|
if c.active?
|
||||||
qbo_customer.save_without_push
|
#if not customer.name.eql? c.display_name
|
||||||
end
|
customer.name = c.display_name
|
||||||
|
customer.id = c.id
|
||||||
|
customer.phone_number = c.primary_phone.free_form_number.tr('^0-9', '') unless c.primary_phone.nil?
|
||||||
|
customer.mobile_phone_number = c.mobile_phone.free_form_number.tr('^0-9', '') unless c.mobile_phone.nil?
|
||||||
|
customer.save_without_push
|
||||||
|
#end
|
||||||
else
|
else
|
||||||
if not qbo_customer.new_record?
|
if not c.new_record?
|
||||||
qbo_customer.delete
|
customer.delete
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -173,19 +177,26 @@ class Customer < ActiveRecord::Base
|
|||||||
# proforms a bruteforce sync operation
|
# proforms a bruteforce sync operation
|
||||||
# This needs to be simplified
|
# This needs to be simplified
|
||||||
def self.sync_by_id(id)
|
def self.sync_by_id(id)
|
||||||
service = Qbo.get_base(:customer)
|
qbo = Qbo.first
|
||||||
|
c = qbo.perform_authenticated_request do |access_token|
|
||||||
|
service = Quickbooks::Service::Customer.new(:company_id => qbo.realm_id, :access_token => access_token)
|
||||||
|
service.fetch_by_id(id)
|
||||||
|
end
|
||||||
|
|
||||||
customer = service.fetch_by_id(id)
|
return unless c
|
||||||
qbo_customer = Customer.find_or_create_by(id: customer.id)
|
|
||||||
if customer.active?
|
customer = Customer.find_or_create_by(id: c.id)
|
||||||
if not qbo_customer.name.eql? customer.display_name
|
if c.active?
|
||||||
qbo_customer.name = customer.display_name
|
#if not customer.name.eql? c.display_name
|
||||||
qbo_customer.id = customer.id
|
customer.name = c.display_name
|
||||||
qbo_customer.save_without_push
|
customer.id = c.id
|
||||||
end
|
customer.phone_number = c.primary_phone.free_form_number.tr('^0-9', '') unless c.primary_phone.nil?
|
||||||
|
customer.mobile_phone_number = c.mobile_phone.free_form_number.tr('^0-9', '') unless c.mobile_phone.nil?
|
||||||
|
customer.save_without_push
|
||||||
|
#end
|
||||||
else
|
else
|
||||||
if not qbo_customer.new_record?
|
if not customer.new_record?
|
||||||
qbo_customer.delete
|
customer.delete
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -193,7 +204,11 @@ class Customer < ActiveRecord::Base
|
|||||||
# Push the updates
|
# Push the updates
|
||||||
def save_with_push
|
def save_with_push
|
||||||
begin
|
begin
|
||||||
@details = Qbo.get_base(:customer).update(@details)
|
qbo = Qbo.first
|
||||||
|
@details = qbo.perform_authenticated_request do |access_token|
|
||||||
|
service = Quickbooks::Service::Customer.new(:company_id => qbo.realm_id, :access_token => access_token)
|
||||||
|
service.update(@details)
|
||||||
|
end
|
||||||
#raise "QBO Fault" if @details.fault?
|
#raise "QBO Fault" if @details.fault?
|
||||||
self.id = @details.id
|
self.id = @details.id
|
||||||
rescue Exception => e
|
rescue Exception => e
|
||||||
@@ -211,7 +226,11 @@ class Customer < ActiveRecord::Base
|
|||||||
def pull
|
def pull
|
||||||
begin
|
begin
|
||||||
raise Exception unless self.id
|
raise Exception unless self.id
|
||||||
@details = Qbo.get_base(:customer).fetch_by_id(self.id)
|
qbo = Qbo.first
|
||||||
|
@details = qbo.perform_authenticated_request do |access_token|
|
||||||
|
service = Quickbooks::Service::Customer.new(:company_id => qbo.realm_id, :access_token => access_token)
|
||||||
|
service.fetch_by_id(self.id)
|
||||||
|
end
|
||||||
rescue Exception => e
|
rescue Exception => e
|
||||||
@details = Quickbooks::Model::Customer.new
|
@details = Quickbooks::Model::Customer.new
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#The MIT License (MIT)
|
#The MIT License (MIT)
|
||||||
#
|
#
|
||||||
#Copyright (c) 2017 rick barrette
|
#Copyright (c) 2024 rick barrette
|
||||||
#
|
#
|
||||||
#Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
#Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
#
|
#
|
||||||
@@ -9,15 +9,53 @@
|
|||||||
#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.
|
#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 CustomerToken < ActiveRecord::Base
|
class CustomerToken < ActiveRecord::Base
|
||||||
unloadable
|
|
||||||
has_many :issues
|
has_many :issues
|
||||||
attr_accessible :token, :expires_at, :issue_id
|
validates_presence_of :issue_id
|
||||||
validates_presence_of :expires_at, :issue_id
|
before_create :generate_token, :generate_expire_date
|
||||||
before_create :generate_token
|
attr_accessor :destroyed
|
||||||
|
after_destroy :mark_as_destroyed
|
||||||
|
|
||||||
OAUTH_CONSUMER_SECRET = Setting.plugin_redmine_qbo['settingsOAuthConsumerSecret'] || 'CONFIGURE_QBO__' + SecureRandom.uuid
|
OAUTH_CONSUMER_SECRET = Setting.plugin_redmine_qbo['settingsOAuthConsumerSecret'] || 'CONFIGURE__' + SecureRandom.uuid
|
||||||
|
|
||||||
|
# generates a random token using the plugin setting settingsOAuthConsumerSecret for salt
|
||||||
def generate_token
|
def generate_token
|
||||||
self.token = SecureRandom.base64(15).tr('+/=lIO0', OAUTH_CONSUMER_SECRET)
|
self.token = SecureRandom.base64(15).tr('+/=lIO0', OAUTH_CONSUMER_SECRET)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# generates an expiring date
|
||||||
|
def generate_expire_date
|
||||||
|
self.expires_at = Time.now + 1.month
|
||||||
|
end
|
||||||
|
|
||||||
|
# set destroyed flag
|
||||||
|
def mark_as_destroyed
|
||||||
|
self.destroyed = true
|
||||||
|
end
|
||||||
|
|
||||||
|
# purge expired tokens
|
||||||
|
def self.remove_expired_tokens
|
||||||
|
where("expires_at < ?", Time.now).destroy_all
|
||||||
|
end
|
||||||
|
|
||||||
|
# has the token expired?
|
||||||
|
def expired?
|
||||||
|
self.expires_at < Time.now
|
||||||
|
end
|
||||||
|
|
||||||
|
# Getter convenience method for tokens
|
||||||
|
def self.get_token(issue)
|
||||||
|
|
||||||
|
# check to see if token exists & if it is expired
|
||||||
|
token = find_by_issue_id issue.id
|
||||||
|
unless token.nil?
|
||||||
|
return token unless token.expired?
|
||||||
|
# remove expired tokens
|
||||||
|
token.destroy
|
||||||
|
end
|
||||||
|
|
||||||
|
# only create new token if we have an issue to attach it to
|
||||||
|
return create(:issue_id => issue.id) if User.current.logged?
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#The MIT License (MIT)
|
#The MIT License (MIT)
|
||||||
#
|
#
|
||||||
#Copyright (c) 2020 rick barrette
|
#Copyright (c) 2024 rick barrette
|
||||||
#
|
#
|
||||||
#Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
#Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
#
|
#
|
||||||
@@ -8,40 +8,43 @@
|
|||||||
#
|
#
|
||||||
#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.
|
#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 QboItem < ActiveRecord::Base
|
class Employee < ActiveRecord::Base
|
||||||
unloadable
|
|
||||||
has_many :issues
|
has_many :users
|
||||||
attr_accessible :name
|
|
||||||
validates_presence_of :id, :name
|
validates_presence_of :id, :name
|
||||||
|
|
||||||
self.primary_key = :id
|
|
||||||
|
|
||||||
def self.get_base
|
|
||||||
Qbo.get_base(:item)
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.sync
|
def self.sync
|
||||||
last = Qbo.first.last_sync
|
qbo = Qbo.first
|
||||||
|
employees = qbo.perform_authenticated_request do |access_token|
|
||||||
query = "SELECT Id, Name FROM Item WHERE Type = 'Service' "
|
service = Quickbooks::Service::Employee.new(:company_id => qbo.realm_id, :access_token => access_token)
|
||||||
query << " AND Metadata.LastUpdatedTime >= '#{last.iso8601}' " if last
|
service.all
|
||||||
|
|
||||||
if count == 0
|
|
||||||
items = get_base.all
|
|
||||||
else
|
|
||||||
items = get_base.query(query)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
unless items.count = 0
|
return unless employees
|
||||||
items.find_by(:type, "Service").each { |i|
|
|
||||||
qbo_item = QboItem.find_or_create_by(id: i.id)
|
transaction do
|
||||||
qbo_item.name = i.name
|
# Update the item table
|
||||||
qbo_item.id = i.id
|
employees.each { |e|
|
||||||
qbo_item.save
|
logger.info "Processing employee #{e.id}"
|
||||||
|
employee = find_or_create_by(id: e.id)
|
||||||
|
employee.name = e.display_name
|
||||||
|
employee.id = e.id
|
||||||
|
employee.save!
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
# QboItem.where.not(items.map(&:id)).destroy_all
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.sync_by_id(id)
|
||||||
|
qbo = Qbo.first
|
||||||
|
employee = qbo.perform_authenticated_request do |access_token|
|
||||||
|
service = Quickbooks::Service::Employee.new(:company_id => qbo.realm_id, :access_token => access_token)
|
||||||
|
service.fetch_by_id(id)
|
||||||
|
end
|
||||||
|
|
||||||
|
return unless employee
|
||||||
|
employee = find_or_create_by(id: employee.id)
|
||||||
|
employee.name = employee.display_name
|
||||||
|
employee.id = employee.id
|
||||||
|
employee.save!
|
||||||
|
end
|
||||||
end
|
end
|
||||||
129
app/models/estimate.rb
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
#The MIT License (MIT)
|
||||||
|
#
|
||||||
|
#Copyright (c) 2024 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 Estimate < ActiveRecord::Base
|
||||||
|
|
||||||
|
has_and_belongs_to_many :issues
|
||||||
|
belongs_to :customer
|
||||||
|
validates_presence_of :doc_number, :id
|
||||||
|
self.primary_key = :id
|
||||||
|
|
||||||
|
# sync all estimates
|
||||||
|
def self.sync
|
||||||
|
logger.info "Syncing ALL estimates"
|
||||||
|
qbo = Qbo.first
|
||||||
|
estimates = qbo.perform_authenticated_request do |access_token|
|
||||||
|
service = Quickbooks::Service::Estimate.new(:company_id => qbo.realm_id, :access_token => access_token)
|
||||||
|
service.all
|
||||||
|
end
|
||||||
|
|
||||||
|
return unless estimates
|
||||||
|
|
||||||
|
estimates.each { |estimate|
|
||||||
|
process_estimate(estimate)
|
||||||
|
}
|
||||||
|
|
||||||
|
#remove deleted estimates
|
||||||
|
where.not(estimates.map(&:id)).destroy_all
|
||||||
|
end
|
||||||
|
|
||||||
|
# sync only one estimate
|
||||||
|
def self.sync_by_id(id)
|
||||||
|
logger.info "Syncing estimate #{id}"
|
||||||
|
qbo = Qbo.first
|
||||||
|
qbo.perform_authenticated_request do |access_token|
|
||||||
|
service = Quickbooks::Service::Estimate.new(:company_id => qbo.realm_id, :access_token => access_token)
|
||||||
|
process_estimate(service.fetch_by_id(id))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# sync only one estimate
|
||||||
|
def self.sync_by_doc_number(number)
|
||||||
|
logger.info "Syncing estimate by doc number #{number}"
|
||||||
|
qbo = Qbo.first
|
||||||
|
qbo.perform_authenticated_request do |access_token|
|
||||||
|
service = Quickbooks::Service::Estimate.new(:company_id => qbo.realm_id, :access_token => access_token)
|
||||||
|
process_estimate(service.find_by( :doc_number, number).first)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# update an estimate
|
||||||
|
def self.update(id)
|
||||||
|
# Update the item table
|
||||||
|
qbo = Qbo.first
|
||||||
|
estimate = qbo.perform_authenticated_request do |access_token|
|
||||||
|
service = Quickbooks::Service::Estimate.new(:company_id => qbo.realm_id, :access_token => access_token)
|
||||||
|
service.fetch_by_id(id)
|
||||||
|
end
|
||||||
|
|
||||||
|
return unless estimate
|
||||||
|
|
||||||
|
e = find_or_create_by(id: id)
|
||||||
|
e.doc_number = estimate.doc_number
|
||||||
|
e.txn_date = estimate.txn_date
|
||||||
|
e.save!
|
||||||
|
end
|
||||||
|
|
||||||
|
# process an estimate into the database
|
||||||
|
def self.process_estimate(qbo_estimate)
|
||||||
|
logger.info "Processing estimate #{qbo_estimate.id}"
|
||||||
|
estimate = find_or_create_by(id: qbo_estimate.id)
|
||||||
|
estimate.doc_number = qbo_estimate.doc_number
|
||||||
|
estimate.customer_id = qbo_estimate.customer_ref.value
|
||||||
|
estimate.id = qbo_estimate.id
|
||||||
|
estimate.txn_date = qbo_estimate.txn_date
|
||||||
|
estimate.save!
|
||||||
|
end
|
||||||
|
|
||||||
|
# download the pdf from quickbooks
|
||||||
|
def pdf
|
||||||
|
qbo = Qbo.first
|
||||||
|
qbo.perform_authenticated_request do |access_token|
|
||||||
|
service = Quickbooks::Service::Estimate.new(:company_id => qbo.realm_id, :access_token => access_token)
|
||||||
|
estimate = service.fetch_by_id(id)
|
||||||
|
service.pdf(estimate)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Magic Method
|
||||||
|
# Maps Get/Set methods to QBO estimate object
|
||||||
|
def method_missing(sym, *arguments)
|
||||||
|
# Check to see if the method exists
|
||||||
|
if Quickbooks::Model::Estimate.method_defined?(sym)
|
||||||
|
# download details if required
|
||||||
|
pull unless @details
|
||||||
|
method_name = sym.to_s
|
||||||
|
# Setter
|
||||||
|
if method_name[-1, 1] == "="
|
||||||
|
@details.method(method_name).call(arguments[0])
|
||||||
|
# Getter
|
||||||
|
else
|
||||||
|
return @details.method(method_name).call
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
# pull the details
|
||||||
|
def pull
|
||||||
|
begin
|
||||||
|
raise Exception unless self.id
|
||||||
|
qbo = Qbo.first
|
||||||
|
@details = qbo.perform_authenticated_request do |access_token|
|
||||||
|
service = Quickbooks::Service::Estimate.new(:company_id => qbo.realm_id, :access_token => access_token)
|
||||||
|
service(:estimate).fetch_by_id(self.id)
|
||||||
|
end
|
||||||
|
rescue Exception => e
|
||||||
|
@details = Quickbooks::Model::Estimate.new
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
205
app/models/invoice.rb
Normal file
@@ -0,0 +1,205 @@
|
|||||||
|
#The MIT License (MIT)
|
||||||
|
#
|
||||||
|
#Copyright (c) 2024 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 Invoice < ActiveRecord::Base
|
||||||
|
|
||||||
|
has_and_belongs_to_many :issues
|
||||||
|
belongs_to :customer
|
||||||
|
validates_presence_of :doc_number, :id, :customer_id, :txn_date
|
||||||
|
self.primary_key = :id
|
||||||
|
|
||||||
|
# sync ALL the invoices
|
||||||
|
def self.sync
|
||||||
|
logger.info "Syncing all invoices"
|
||||||
|
last = Qbo.first.last_sync
|
||||||
|
|
||||||
|
query = "SELECT Id, DocNumber FROM Invoice"
|
||||||
|
query << " WHERE Metadata.LastUpdatedTime >= '#{last.iso8601}' " if last
|
||||||
|
|
||||||
|
# TODO actually do something with the above query
|
||||||
|
# .all() is never called since count is never initialized
|
||||||
|
qbo = Qbo.first
|
||||||
|
invoices = qbo.perform_authenticated_request do |access_token|
|
||||||
|
service = Quickbooks::Service::Invoice.new(:company_id => qbo.realm_id, :access_token => access_token)
|
||||||
|
service.all
|
||||||
|
end
|
||||||
|
|
||||||
|
return unless invoices
|
||||||
|
|
||||||
|
invoices.each { | invoice |
|
||||||
|
process_invoice invoice
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
#sync by invoice ID
|
||||||
|
def self.sync_by_id(id)
|
||||||
|
logger.info "Syncing invoice #{id}"
|
||||||
|
qbo = Qbo.first
|
||||||
|
qbo.perform_authenticated_request do |access_token|
|
||||||
|
service = Quickbooks::Service::Invoice.new(:company_id => qbo.realm_id, :access_token => access_token)
|
||||||
|
invoice = service.fetch_by_id(id)
|
||||||
|
process_invoice invoice
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
# Attach the invoice to the issue
|
||||||
|
def self.attach_to_issue(issue, invoice)
|
||||||
|
return if issue.nil?
|
||||||
|
|
||||||
|
# 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.info "Attaching invoice #{invoice.id} to issue #{issue.id}"
|
||||||
|
|
||||||
|
invoice = Invoice.find_or_create_by(id: invoice.id)
|
||||||
|
|
||||||
|
unless issue.invoices.include?(invoice)
|
||||||
|
issue.invoices << invoice
|
||||||
|
issue.save!
|
||||||
|
end
|
||||||
|
|
||||||
|
compare_custom_fields(issue, invoice)
|
||||||
|
end
|
||||||
|
|
||||||
|
# processes the invoice into the database
|
||||||
|
def self.process_invoice(i)
|
||||||
|
logger.info "Processing invoice #{i.id}"
|
||||||
|
|
||||||
|
# Load the invoice into the database
|
||||||
|
invoice = Invoice.find_or_create_by(id: i.id)
|
||||||
|
invoice.doc_number = i.doc_number
|
||||||
|
invoice.id = i.id
|
||||||
|
invoice.customer_id = i.customer_ref
|
||||||
|
invoice.txn_date = i.txn_date
|
||||||
|
invoice.save!
|
||||||
|
|
||||||
|
# Scan the private notes for hashtags and attach to the applicable issues
|
||||||
|
if not i.private_note.nil?
|
||||||
|
i.private_note.scan(/#(\w+)/).flatten.each { |issue|
|
||||||
|
attach_to_issue(Issue.find_by_id(issue.to_i), invoice)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
# Scan the line items for hashtags and attach to the applicable issues
|
||||||
|
i.line_items.each { |line|
|
||||||
|
if line.description
|
||||||
|
line.description.scan(/#(\w+)/).flatten.each { |issue|
|
||||||
|
attach_to_issue(Issue.find_by_id(issue.to_i), invoice)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
# compares the custome fields on invoices & issues and updates the invoice as needed
|
||||||
|
#
|
||||||
|
# the issue here is when two or more issues share an invoice with the same custom field, but diffrent values
|
||||||
|
# this condions causes an infinite loop as the webhook is called when an invoice is updated
|
||||||
|
# TODO maybe add a cf_sync_confict flag to invoices
|
||||||
|
def self.compare_custom_fields(issue, invoice)
|
||||||
|
logger.info "Comparing custom fields"
|
||||||
|
# TODO break if Invoice.find(invoice.id).cf_sync_confict
|
||||||
|
is_changed = false
|
||||||
|
|
||||||
|
# update the invoive custom fields with infomation from the issue if available
|
||||||
|
invoice.custom_fields.each { |cf|
|
||||||
|
|
||||||
|
# VIN from the attached vehicle
|
||||||
|
# TODO move this into seperate plugin
|
||||||
|
# TODO create hook for seperate plugin
|
||||||
|
begin
|
||||||
|
if cf.name.eql? "VIN"
|
||||||
|
# Only update if blank to prevent infite loops
|
||||||
|
# TODO check cf_sync_confict flag once implemented
|
||||||
|
if cf.string_value.to_s.blank?
|
||||||
|
logger.info " VIN was blank, updating the invoice vin in quickbooks"
|
||||||
|
vin = Vehicle.find(issue.vehicles_id).vin
|
||||||
|
break if vin.nil?
|
||||||
|
if not cf.string_value.to_s.eql? vin
|
||||||
|
cf.string_value = vin.to_s
|
||||||
|
logger.info "VIN has changed"
|
||||||
|
is_changed = true
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
rescue
|
||||||
|
#do nothing
|
||||||
|
end
|
||||||
|
|
||||||
|
# Custom Values
|
||||||
|
begin
|
||||||
|
value = issue.custom_values.find_by(custom_field_id: CustomField.find_by_name(cf.name).id)
|
||||||
|
|
||||||
|
# Check to see if the value is blank...
|
||||||
|
if not value.value.to_s.blank?
|
||||||
|
# Check to see if the value is diffrent
|
||||||
|
if not cf.string_value.to_s.eql? value.value.to_s
|
||||||
|
# update the custom field on the invoice
|
||||||
|
cf.string_value = value.value.to_s
|
||||||
|
is_changed = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
rescue
|
||||||
|
# Nothing to do here, there is no match
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
|
# Push updates
|
||||||
|
begin
|
||||||
|
logger.info "Trying to update invoice"
|
||||||
|
qbo = Qbo.first
|
||||||
|
qbo.perform_authenticated_request do |access_token|
|
||||||
|
service = Quickbooks::Service::Invoice.new(:company_id => qbo.realm_id, :access_token => access_token)
|
||||||
|
service.update(invoice) if is_changed
|
||||||
|
end
|
||||||
|
rescue
|
||||||
|
# Do nothing, probaly custome field sync confict on the invoice.
|
||||||
|
# This is a problem with how it's billed
|
||||||
|
# TODO Add notes in memo area
|
||||||
|
# TODO flag Invoice.cf_sync_confict here
|
||||||
|
logger.error "Failed to update invoice"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Magic Method
|
||||||
|
# Maps Get/Set methods to QBO invoice object
|
||||||
|
def method_missing(sym, *arguments)
|
||||||
|
# Check to see if the method exists
|
||||||
|
if Quickbooks::Model::Invoice.method_defined?(sym)
|
||||||
|
# download details if required
|
||||||
|
pull unless @details
|
||||||
|
method_name = sym.to_s
|
||||||
|
# Setter
|
||||||
|
if method_name[-1, 1] == "="
|
||||||
|
@details.method(method_name).call(arguments[0])
|
||||||
|
# Getter
|
||||||
|
else
|
||||||
|
return @details.method(method_name).call
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# pull the details from quickbooks
|
||||||
|
def pull
|
||||||
|
begin
|
||||||
|
raise Exception unless self.id
|
||||||
|
qbo = Qbo.first
|
||||||
|
@details = qbo.perform_authenticated_request do |access_token|
|
||||||
|
service = Quickbooks::Service::Invoice.new(:company_id => qbo.realm_id, :access_token => access_token)
|
||||||
|
service.fetch_by_id(self.id)
|
||||||
|
end
|
||||||
|
rescue Exception => e
|
||||||
|
@details = Quickbooks::Model::Invoice.new
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
#The MIT License (MIT)
|
#The MIT License (MIT)
|
||||||
#
|
#
|
||||||
#Copyright (c) 2020 rick barrette
|
#Copyright (c) 2016 - 2025 rick barrette
|
||||||
#
|
#
|
||||||
#Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
#Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
#
|
#
|
||||||
@@ -9,78 +9,16 @@
|
|||||||
#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.
|
#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 Qbo < ActiveRecord::Base
|
class Qbo < ActiveRecord::Base
|
||||||
unloadable
|
|
||||||
validates_presence_of :qb_token, :qb_secret, :company_id, :token_expires_at, :reconnect_token_at
|
|
||||||
serialize :token
|
|
||||||
|
|
||||||
OAUTH_CONSUMER_KEY = Setting.plugin_redmine_qbo['settingsOAuthConsumerKey']
|
include QuickbooksOauth
|
||||||
OAUTH_CONSUMER_SECRET = Setting.plugin_redmine_qbo['settingsOAuthConsumerSecret']
|
include Redmine::I18n
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
def self.get_oauth_consumer
|
|
||||||
# Quickbooks Config Info
|
|
||||||
return $qb_oauth_consumer
|
|
||||||
end
|
|
||||||
|
|
||||||
# Get a quickbooks base service object for type
|
|
||||||
# @params type of base
|
|
||||||
def self.get_base(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
|
|
||||||
def self.get_account
|
|
||||||
first
|
|
||||||
end
|
|
||||||
|
|
||||||
# Updates last sync time stamp
|
# Updates last sync time stamp
|
||||||
def self.update_time_stamp
|
def self.update_time_stamp
|
||||||
|
date = DateTime.now
|
||||||
|
logger.info "Updating QBO timestamp to #{date}"
|
||||||
qbo = Qbo.first
|
qbo = Qbo.first
|
||||||
qbo.last_sync = DateTime.now
|
qbo.last_sync = date
|
||||||
qbo.save
|
qbo.save
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -1,58 +0,0 @@
|
|||||||
#The MIT License (MIT)
|
|
||||||
#
|
|
||||||
#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:
|
|
||||||
#
|
|
||||||
#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 QboEstimate < ActiveRecord::Base
|
|
||||||
unloadable
|
|
||||||
|
|
||||||
has_and_belongs_to_many :issues
|
|
||||||
belongs_to :customer
|
|
||||||
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)
|
|
||||||
end
|
|
||||||
|
|
||||||
# sync all estimates
|
|
||||||
def self.sync
|
|
||||||
estimates = get_base.all
|
|
||||||
estimates.each { |estimate|
|
|
||||||
process_estimate(estimate)
|
|
||||||
}
|
|
||||||
|
|
||||||
#remove deleted estimates
|
|
||||||
where.not(estimates.map(&:id)).destroy_all
|
|
||||||
end
|
|
||||||
|
|
||||||
# sync only one estimate
|
|
||||||
def self.sync_by_id(id)
|
|
||||||
process_estimate(get_base.fetch_by_id(id))
|
|
||||||
end
|
|
||||||
|
|
||||||
# update an estimate
|
|
||||||
def self.update(id)
|
|
||||||
# Update the item table
|
|
||||||
estimate = get_base.fetch_by_id(id)
|
|
||||||
qbo_estimate = find_or_create_by(id: id)
|
|
||||||
qbo_estimate.doc_number = estimate.doc_number
|
|
||||||
qbo_estimate.save!
|
|
||||||
end
|
|
||||||
|
|
||||||
# process an estimate into the database
|
|
||||||
def self.process_estimate(estimate)
|
|
||||||
qbo_estimate = find_or_create_by(id: estimate.id)
|
|
||||||
qbo_estimate.doc_number = estimate.doc_number
|
|
||||||
qbo_estimate.customer_id = estimate.customer_ref.value
|
|
||||||
qbo_estimate.id = estimate.id
|
|
||||||
qbo_estimate.save!
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -1,155 +0,0 @@
|
|||||||
#The MIT License (MIT)
|
|
||||||
#
|
|
||||||
#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:
|
|
||||||
#
|
|
||||||
#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 QboInvoice < ActiveRecord::Base
|
|
||||||
unloadable
|
|
||||||
|
|
||||||
has_and_belongs_to_many :issues
|
|
||||||
belongs_to :customer
|
|
||||||
attr_accessible :doc_number, :id
|
|
||||||
validates_presence_of :doc_number, :id
|
|
||||||
self.primary_key = :id
|
|
||||||
|
|
||||||
def self.get_base
|
|
||||||
Qbo.get_base(:invoice)
|
|
||||||
end
|
|
||||||
|
|
||||||
# sync ALL the invoices
|
|
||||||
def self.sync
|
|
||||||
last = Qbo.first.last_sync
|
|
||||||
|
|
||||||
query = "SELECT Id, DocNumber FROM Invoice"
|
|
||||||
query << " WHERE Metadata.LastUpdatedTime >= '#{last.iso8601}' " if last
|
|
||||||
|
|
||||||
if count == 0
|
|
||||||
invoices = get_base.all
|
|
||||||
else
|
|
||||||
invoices = get_base.query()
|
|
||||||
end
|
|
||||||
|
|
||||||
# Update the invoice table
|
|
||||||
invoices.each { | invoice |
|
|
||||||
process_invoice invoice
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
#sync by invoice ID
|
|
||||||
def self.sync_by_id(id)
|
|
||||||
#update the information in the database
|
|
||||||
invoice = get_base.fetch_by_id(id)
|
|
||||||
process_invoice invoice
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
# Attach the invoice to the issue
|
|
||||||
def self.attach_to_issue(issue, invoice)
|
|
||||||
return if issue.nil?
|
|
||||||
|
|
||||||
# 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
|
|
||||||
|
|
||||||
# Load the invoice into the database
|
|
||||||
qbo_invoice = QboInvoice.find_or_create_by(id: invoice.id)
|
|
||||||
qbo_invoice.doc_number = invoice.doc_number
|
|
||||||
qbo_invoice.id = invoice.id
|
|
||||||
qbo_invoice.customer_id = invoice.customer_ref
|
|
||||||
qbo_invoice.save!
|
|
||||||
|
|
||||||
unless issue.qbo_invoices.include?(qbo_invoice)
|
|
||||||
issue.qbo_invoices << qbo_invoice
|
|
||||||
issue.save!
|
|
||||||
end
|
|
||||||
|
|
||||||
compare_custom_fields(issue, invoice)
|
|
||||||
end
|
|
||||||
|
|
||||||
# processes the invoice into the system
|
|
||||||
def self.process_invoice(invoice)
|
|
||||||
# Check the private notes
|
|
||||||
if not invoice.private_note.nil?
|
|
||||||
invoice.private_note.scan(/#(\w+)/).flatten.each { |issue|
|
|
||||||
attach_to_issue(Issue.find_by_id(issue.to_i), invoice)
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
# Scan the line items for hashtags and attach to the applicable issues
|
|
||||||
invoice.line_items.each { |line|
|
|
||||||
if line.description
|
|
||||||
line.description.scan(/#(\w+)/).flatten.each { |issue|
|
|
||||||
attach_to_issue(Issue.find_by_id(issue.to_i), invoice)
|
|
||||||
}
|
|
||||||
end
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.compare_custom_fields(issue, invoice)
|
|
||||||
is_changed = false
|
|
||||||
|
|
||||||
# update the invoive custom fields with infomation from the work ticket if available
|
|
||||||
invoice.custom_fields.each { |cf|
|
|
||||||
|
|
||||||
# TODO Add some hooks here
|
|
||||||
|
|
||||||
# VIN from the attached vehicle
|
|
||||||
begin
|
|
||||||
if cf.name.eql? "VIN"
|
|
||||||
vin = Vehicle.find(issue.vehicles_id).vin
|
|
||||||
break if vin.nil?
|
|
||||||
if not cf.string_value.to_s.eql? vin
|
|
||||||
cf.string_value = vin.to_s
|
|
||||||
is_changed = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
rescue
|
|
||||||
#do nothing
|
|
||||||
end
|
|
||||||
|
|
||||||
# Custom Values
|
|
||||||
begin
|
|
||||||
value = issue.custom_values.find_by(custom_field_id: CustomField.find_by_name(cf.name).id)
|
|
||||||
|
|
||||||
# Check to see if the value is blank...
|
|
||||||
if not value.value.to_s.blank?
|
|
||||||
# Check to see if the value is diffrent
|
|
||||||
if not cf.string_value.to_s.eql? value.value.to_s
|
|
||||||
|
|
||||||
# Use the lowest Milage
|
|
||||||
if cf.name.eql? "Mileage In"
|
|
||||||
if cf.string_value.to_i > value.value.to_i or cf.string_value.blank?
|
|
||||||
cf.string_value = value.value.to_s
|
|
||||||
is_changed = true
|
|
||||||
end
|
|
||||||
# Use the max milage
|
|
||||||
elsif cf.name.eql? "Mileage Out"
|
|
||||||
if cf.string_value.to_i < value.value.to_i or cf.string_value.blank?
|
|
||||||
cf.string_value = value.value.to_s
|
|
||||||
is_changed = true
|
|
||||||
end
|
|
||||||
else
|
|
||||||
# Everything else
|
|
||||||
cf.string_value = value.value.to_s
|
|
||||||
is_changed = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
rescue
|
|
||||||
# Nothing to do here, there is no match
|
|
||||||
end
|
|
||||||
}
|
|
||||||
|
|
||||||
# TODO Add some hooks here
|
|
||||||
|
|
||||||
# Push updates
|
|
||||||
#invoice.sync_token += 1 if is_changed
|
|
||||||
get_base.update(invoice) if is_changed
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
#The MIT License (MIT)
|
|
||||||
#
|
|
||||||
#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:
|
|
||||||
#
|
|
||||||
#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 QboPurchase < ActiveRecord::Base
|
|
||||||
unloadable
|
|
||||||
belongs_to :issues
|
|
||||||
belongs_to :qbo_customer
|
|
||||||
attr_accessible :description
|
|
||||||
validates_presence_of :id, :line_id, :description, :qbo_customer_id
|
|
||||||
|
|
||||||
def self.get_base
|
|
||||||
Qbo.get_base(:purchase)
|
|
||||||
end
|
|
||||||
|
|
||||||
def get_purchase(id)
|
|
||||||
get_base.find_by_id(id)
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.sync
|
|
||||||
QboPurchase.get_base.all.each { |purchase|
|
|
||||||
|
|
||||||
purchase.line_items.all? { |line_item|
|
|
||||||
|
|
||||||
detail = line_item.account_based_expense_line_detail ? line_item.account_based_expense_line_detail : line_item.item_based_expense_line_detail
|
|
||||||
|
|
||||||
if detail.billable_status = "Billable"
|
|
||||||
qbo_purchase = find_or_create_by(id: purchase.id)
|
|
||||||
qbo_purchase.line_id = line_item.id
|
|
||||||
qbo_purchase.description = line_item.description
|
|
||||||
qbo_purchase.qbo_customer_id = detail.customer_ref
|
|
||||||
|
|
||||||
#TODO attach to issues
|
|
||||||
#qbo_purchase.issue_id = Issue.find_by_invoice()
|
|
||||||
|
|
||||||
qbo_purchase.save
|
|
||||||
end
|
|
||||||
}
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
#The MIT License (MIT)
|
#The MIT License (MIT)
|
||||||
#
|
#
|
||||||
#Copyright (c) 2017 rick barrette
|
#Copyright (c) 2024 rick barrette
|
||||||
#
|
#
|
||||||
#Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
#Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
#
|
#
|
||||||
@@ -10,17 +10,12 @@
|
|||||||
|
|
||||||
class Vehicle < ActiveRecord::Base
|
class Vehicle < ActiveRecord::Base
|
||||||
|
|
||||||
unloadable
|
|
||||||
|
|
||||||
belongs_to :customer
|
belongs_to :customer
|
||||||
has_many :issues, :foreign_key => 'vehicles_id'
|
has_many :issues, :foreign_key => 'vehicles_id'
|
||||||
|
|
||||||
attr_accessible :year, :make, :model, :customer_id, :notes, :vin
|
|
||||||
|
|
||||||
validates_presence_of :customer
|
validates_presence_of :customer
|
||||||
validates :vin, uniqueness: true
|
validates :vin, uniqueness: true
|
||||||
before_save :decode_vin
|
before_save :decode_vin
|
||||||
#after_find :get_details
|
|
||||||
|
|
||||||
self.primary_key = :id
|
self.primary_key = :id
|
||||||
|
|
||||||
@@ -34,35 +29,12 @@ class Vehicle < ActiveRecord::Base
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# returns the raw JSON details from EMUNDS
|
# returns the raw JSON details from NHTSA
|
||||||
def details
|
def details
|
||||||
get_details if @details.nil?
|
get_details if @details.nil?
|
||||||
return @details
|
return @details
|
||||||
end
|
end
|
||||||
|
|
||||||
# returns the style of the vehicle
|
|
||||||
def style
|
|
||||||
get_details if @details.nil?
|
|
||||||
begin
|
|
||||||
return @details.trim if @details
|
|
||||||
rescue
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# returns the drive of the vehicle i.e. 2 wheel, 4 wheel, ect.
|
|
||||||
def drive
|
|
||||||
#todo fix this
|
|
||||||
#return @details.drive_type if @details
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
# 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 make numbers
|
# Force Upper Case for make numbers
|
||||||
def make=(val)
|
def make=(val)
|
||||||
# The to_s is in case you get nil/non-string
|
# The to_s is in case you get nil/non-string
|
||||||
@@ -75,9 +47,8 @@ class Vehicle < ActiveRecord::Base
|
|||||||
write_attribute(:model, val.to_s.titleize)
|
write_attribute(:model, val.to_s.titleize)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Force Upper Case for VIN numbers
|
# Force Upper Case & strip VIN of all illegal chars (for barcode scanner)
|
||||||
def vin=(val)
|
def vin=(val)
|
||||||
#strip VIN of all illegal chars (for barcode scanner)
|
|
||||||
val = val.to_s.upcase.gsub(/[^A-HJ-NPR-Za-hj-npr-z\d]+/,"")
|
val = val.to_s.upcase.gsub(/[^A-HJ-NPR-Za-hj-npr-z\d]+/,"")
|
||||||
write_attribute(:vin, val)
|
write_attribute(:vin, val)
|
||||||
end
|
end
|
||||||
@@ -93,8 +64,10 @@ class Vehicle < ActiveRecord::Base
|
|||||||
if @details
|
if @details
|
||||||
begin
|
begin
|
||||||
self.year = @details.year unless @details.year.nil?
|
self.year = @details.year unless @details.year.nil?
|
||||||
self.make = @details.make unless @details.make.nil?
|
self.make = @details.make unless @details.make.nil?
|
||||||
self.model = @details.model unless @details.model.nil?
|
self.model = @details.model unless @details.model.nil?
|
||||||
|
self.doors = @details.doors unless @details.doors.nil?
|
||||||
|
self.trim = @details.trim unless @details.trim.nil?
|
||||||
rescue Exception => e
|
rescue Exception => e
|
||||||
errors.add(:vin, e.message)
|
errors.add(:vin, e.message)
|
||||||
end
|
end
|
||||||
@@ -102,17 +75,17 @@ class Vehicle < ActiveRecord::Base
|
|||||||
self.name = to_s
|
self.name = to_s
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
# init method to pull JSON details from Edmunds
|
# init method to pull JSON details from NHTSA
|
||||||
def get_details
|
def get_details
|
||||||
if self.vin?
|
if self.vin?
|
||||||
#validate the vin before calling a remote server
|
#validate the vin before calling a remote server
|
||||||
validation = NhtsaVin.validate(self.vin)
|
validation = NhtsaVin.validate(self.vin)
|
||||||
begin
|
begin
|
||||||
#if the vin validation failed, raise an exception and exit
|
#if the vin validation failed, raise an exception and exit
|
||||||
raise RuntimeError, validation.error unless validation.valid?
|
raise RuntimeError, validation.error unless validation.valid?
|
||||||
# query NHTSA for details on the vin
|
# query NHTSA for details on the vin
|
||||||
query = NhtsaVin.get(self.vin)
|
query = NhtsaVin.get(self.vin)
|
||||||
raise RuntimeError, query.error unless query.valid?
|
raise RuntimeError, query.error unless query.valid?
|
||||||
@details = query.response
|
@details = query.response
|
||||||
|
|||||||
11
app/views/customers/_actions.html.erb
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<%= link_to t(:label_appointment), "https://calendar.google.com/calendar/render?action=TEMPLATE&text=#{@customer.name}+-&details=#{ link_to "Customer Details", "https://#{Setting.host_name}#{customer_path @customer.id}"}%0A#{@customer.primary_phone}&dates=#{Time.now.strftime("%Y%m%d")}T090000/#{Time.now.strftime("%Y%m%d")}T170000", target: :_blank %>
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
<%= link_to t(:label_create_estimate), "https://qbo.intuit.com/app/estimate?nameId=#{@customer.id}", target: :_blank %>
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
<%= button_to t(:label_edit_customer), edit_customer_path(@customer), method: :get%>
|
||||||
@@ -1,54 +1,46 @@
|
|||||||
<table>
|
<table>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<th>Email</th>
|
<th><%=t(:label_name)%></th>
|
||||||
|
<td><%= customer.name %></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<th><%=t(:label_email)%></th>
|
||||||
<td><%= customer.email %></td>
|
<td><%= customer.email %></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<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>
|
<td><%= number_to_phone(customer.primary_phone.gsub(/[^\d]/, '').to_i, area_code: true) if customer.primary_phone %></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<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>
|
<td><%= number_to_phone(customer.mobile_phone.gsub(/[^\d]/, '').to_i, area_code: true) if customer.mobile_phone %></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<th>Bill Address</th>
|
<th><%=t(:label_billing_address)%></th>
|
||||||
<td><%= customer.billing_address %></td>
|
<td><%= @billing_address %></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<th>Shipping Address</th>
|
<th><%=t(:label_shipping_address)%></th>
|
||||||
<td><%= customer.shipping_address %></td>
|
<td><%= @shipping_address %></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<th>Issues</th>
|
<th><%=t(:label_account_balance)%></th>
|
||||||
<td><%= customer.issues.count %></td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<th>Account Balance</th>
|
|
||||||
<td>$<%= customer.balance %></td>
|
<td>$<%= customer.balance %></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<th>Balance With Jobs</th>
|
<th><%=t(:field_notes)%></th>
|
||||||
<td>$<%= customer.balance_with_jobs %></td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<th>Notes</th>
|
|
||||||
<td><%= customer.notes %></td>
|
<td><%= customer.notes %></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<%= button_to "Edit Customer", edit_customer_path(customer), method: :get%>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
|||||||
@@ -5,35 +5,35 @@
|
|||||||
<%= form_for @customer do |f| %>
|
<%= form_for @customer do |f| %>
|
||||||
|
|
||||||
<div class="clearfix">
|
<div class="clearfix">
|
||||||
Display Name:
|
<%=t(:label_display_name)%>
|
||||||
<div class="input">
|
<div class="input">
|
||||||
<%= f.text_field :name, :required => true %>
|
<%= f.text_field :name, :required => true, :autocomplete => "off" %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="clearfix">
|
<div class="clearfix">
|
||||||
Phone Number:
|
<%=t(:label_primary_phone)%>
|
||||||
<div class="input">
|
<div class="input">
|
||||||
<%= f.telephone_field :primary_phone %>
|
<%= f.telephone_field :primary_phone, :autocomplete => "off" %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="clearfix">
|
<div class="clearfix">
|
||||||
Mobile Phone Number:
|
<%=t(:label_mobile_phone)%>:
|
||||||
<div class="input">
|
<div class="input">
|
||||||
<%= f.telephone_field :mobile_phone %>
|
<%= f.telephone_field :mobile_phone, :autocomplete => "off" %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="clearfix">
|
<div class="clearfix">
|
||||||
Email:
|
<%=t(:label_email)%>:
|
||||||
<div class="input">
|
<div class="input">
|
||||||
<%= f.email_field :email %>
|
<%= f.email_field :email, :autocomplete => "off" %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="clearfix">
|
<div class="clearfix">
|
||||||
Notes:
|
<%=t(:field_notes)%>:
|
||||||
<div class="input">
|
<div class="input">
|
||||||
<p>
|
<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? %>
|
<%= link_to_function content_tag(:span, l(:button_edit), :class => 'icon icon-edit'), '$(this).hide(); $("#issue_description_and_toolbar").show()' unless @customer.new_record? %>
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
<%= form_tag(customers_path, :method => "get", id: "search-form") do %>
|
<%= form_tag(customers_path, :method => "get", id: "search-form") do %>
|
||||||
<%= text_field_tag :search, params[:search], placeholder: "Search Customers" %>
|
<%= text_field_tag :search, params[:search], placeholder: t(:label_search_customers), :autocomplete => "off" %>
|
||||||
<%= submit_tag "Search" %>
|
<%= submit_tag t(:label_search) %>
|
||||||
<% end %>
|
<% end %>
|
||||||
<%= button_to "New Customer", new_customer_path, method: :get%>
|
<%= button_to t(:label_new_customer), new_customer_path, method: :get%>
|
||||||
<%= button_to "Sync", qbo_sync_path, method: :get%>
|
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
<h3>Customers</h3>
|
<h3><%=t(:label_customers)%></h3>
|
||||||
<%= render :partial => 'customers/search' %>
|
<%= render :partial => 'customers/search' %>
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
<h1>Edit Customer</h1>
|
<h1><%=t(:label_edit_customer)%></h1>
|
||||||
<br/>
|
<br/>
|
||||||
<%= render :partial => 'customers/form' %>
|
<%= render :partial => 'customers/form' %>
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
$('select#issue_qbo_estimate_id').html('<%= j content_tag(:option,'',:value=>"")+options_from_collection_for_select(@filtered_estimates, :id, :doc_number) %>');
|
$('select#issue_estimate_id').html('<%= j content_tag(:option,'',:value=>"")+options_from_collection_for_select(@filtered_estimates, :id, :doc_number) %>');
|
||||||
|
|||||||
@@ -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? %>
|
<% if @customers.present? %>
|
||||||
<br/>
|
<br/>
|
||||||
<% @customers.each do |c| %>
|
<% @customers.each do |c| %>
|
||||||
@@ -9,14 +9,14 @@
|
|||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<p>Matching <%= @customers.count %> Customers </p>
|
<p><%=t(:label_matching)%> <%= @customers.count %> <%=t(:field_customers)%> </p>
|
||||||
|
|
||||||
<div class="actions">
|
<div class="actions">
|
||||||
<%= will_paginate @customers %>
|
<%= will_paginate @customers %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<% else %>
|
<% else %>
|
||||||
<p>There are no customers containing the term(s) <%= params[:search] %>.</p>
|
<p><%=t(:label_no_customers)%> <%= params[:search] %>.</p>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
<h2>New Customer</h2>
|
<h2><%=t(:label_new_customer)%></h2>
|
||||||
<br/>
|
<br/>
|
||||||
<%= render :partial => 'customers/form' %>
|
<%= render :partial => 'customers/form' %>
|
||||||
|
|||||||
@@ -1,24 +1,57 @@
|
|||||||
<h2>Customer #<%= @customer.id %> - <%= @customer.name %> </h2>
|
<h2><%=t(:field_customer)%> #<%= @customer.id %> - <%= link_to @customer.to_s, "https://app.qbo.intuit.com/app/customerdetail?nameId=#{@customer.id}", target: :_blank %> </h2>
|
||||||
<br/>
|
<div class="issue">
|
||||||
|
|
||||||
<div class="subject">
|
|
||||||
<div><h3>Details:</h3></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="attributes">
|
|
||||||
|
|
||||||
<div class="splitcontent">
|
<div class="splitcontent">
|
||||||
|
|
||||||
<div class="splitcontentleft">
|
<div class="splitcontentleft">
|
||||||
<%= render :partial => 'customers/details', locals: {customer: @customer} %>
|
|
||||||
|
<h4><%=t(:label_details)%>:</h4>
|
||||||
|
|
||||||
|
<!-- Customer Info -->
|
||||||
|
|
||||||
|
<div class="splitcontent">
|
||||||
|
<div class="splitcontentleft">
|
||||||
|
<h4><%=t(:label_customer)%>:</h4>
|
||||||
|
<%= render :partial => 'customers/details', locals: {customer: @customer} %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="splitcontentleft">
|
||||||
|
<h4><%=t(:label_actions)%>:</h4>
|
||||||
|
<%= render :partial => 'customers/actions', locals: {customer: @customer} %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- QBO Info -->
|
||||||
|
|
||||||
|
<div class="splitcontent">
|
||||||
|
<div class="splitcontentleft">
|
||||||
|
<h4><%=t(:estimates)%>:</h4>
|
||||||
|
<%= render :partial => 'estimates/list', locals: {customer: @customer} %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="splitcontentleft">
|
||||||
|
<h4><%=t(:label_invoices)%>:</h4>
|
||||||
|
<%= render :partial => 'invoices/list', locals: {customer: @customer} %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="splitcontentleft">
|
<div class="splitcontentleft">
|
||||||
<h4>Vehicles:</h4>
|
<h4><%=t(:field_vehicles)%>:</h4>
|
||||||
<%= render :partial => 'vehicles/list' %>
|
<%= render :partial => 'vehicles/list' %>
|
||||||
<%= button_to "New Vehicle", new_customer_vehicle_path(@customer), method: :get %>
|
<div style="float: right;">
|
||||||
|
<%= button_to "New Vehicle", new_customer_vehicle_path(@customer), method: :get %>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<br/>
|
|
||||||
<h2>Issues:</h2>
|
|
||||||
<%= render :partial => 'issues/list_simple', locals: {issues: @issues} %>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
<h3><%=@issues.open.count%> <%=t(:label_open_issues)%> - <%=@hours.round(1)%> <%=t(:label_hours)%></h3>
|
||||||
|
<%= render :partial => 'issues/list_simple', locals: {issues: @issues.open} %>
|
||||||
|
|
||||||
|
<h3><%=@closed_issues.count%> <%=t(:label_closed_issues)%> - <%= @closed_hours.round(1)%> <%=t(:label_hours)%></h3>
|
||||||
|
<%= render :partial => 'issues/list_simple', locals: {issues: @closed_issues} %>
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
<p style="float: right;"> <%= copy_object_url_link(request.url) %> </p>
|
||||||
|
|
||||||
<h2><%= issue_heading(@issue) %></h2>
|
<h2><%= issue_heading(@issue) %></h2>
|
||||||
|
|
||||||
<div class="<%= @issue.css_classes %> details">
|
<div class="<%= @issue.css_classes %> details">
|
||||||
@@ -5,8 +7,8 @@
|
|||||||
<%= avatar(@issue.author, :size => "50") %>
|
<%= avatar(@issue.author, :size => "50") %>
|
||||||
|
|
||||||
<div class="subject">
|
<div class="subject">
|
||||||
<%= render_issue_subject_with_tree(@issue) %>
|
<%= 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>
|
</div>
|
||||||
<p class="author">
|
<p class="author">
|
||||||
<%= authoring @issue.created_on, @issue.author %>.
|
<%= authoring @issue.created_on, @issue.author %>.
|
||||||
@@ -20,13 +22,13 @@ This customer link expires in <%= distance_of_time_in_words(Time.now, @token.exp
|
|||||||
rows.left l(:field_status), @issue.status.name, :class => 'status'
|
rows.left l(:field_status), @issue.status.name, :class => 'status'
|
||||||
rows.left l(:field_priority), @issue.priority.name, :class => 'priority'
|
rows.left l(:field_priority), @issue.priority.name, :class => 'priority'
|
||||||
unless @issue.disabled_core_fields.include?('assigned_to_id')
|
unless @issue.disabled_core_fields.include?('assigned_to_id')
|
||||||
rows.left l(:field_assigned_to), avatar(@issue.assigned_to, :size => "14").to_s.html_safe + (@issue.assigned_to ? link_to_user(@issue.assigned_to) : "-"), :class => 'assigned-to'
|
rows.left l(:field_assigned_to), avatar(@issue.assigned_to, :size => "14").to_s.html_safe + (@issue.assigned_to ? @issue.assigned_to : "-"), :class => 'assigned-to'
|
||||||
end
|
end
|
||||||
unless @issue.disabled_core_fields.include?('category_id') || (@issue.category.nil? && @issue.project.issue_categories.none?)
|
unless @issue.disabled_core_fields.include?('category_id') || (@issue.category.nil? && @issue.project.issue_categories.none?)
|
||||||
rows.left l(:field_category), (@issue.category ? @issue.category.name : "-"), :class => 'category'
|
rows.left l(:field_category), (@issue.category ? @issue.category.name : "-"), :class => 'category'
|
||||||
end
|
end
|
||||||
unless @issue.disabled_core_fields.include?('fixed_version_id') || (@issue.fixed_version.nil? && @issue.assignable_versions.none?)
|
unless @issue.disabled_core_fields.include?('fixed_version_id') || (@issue.fixed_version.nil? && @issue.assignable_versions.none?)
|
||||||
rows.left l(:field_fixed_version), (@issue.fixed_version ? link_to_version(@issue.fixed_version) : "-"), :class => 'fixed-version'
|
rows.left l(:field_fixed_version), (@issue.fixed_version ? @issue.fixed_version : "-"), :class => 'fixed-version'
|
||||||
end
|
end
|
||||||
unless @issue.disabled_core_fields.include?('start_date')
|
unless @issue.disabled_core_fields.include?('start_date')
|
||||||
rows.right l(:field_start_date), format_date(@issue.start_date), :class => 'start-date'
|
rows.right l(:field_start_date), format_date(@issue.start_date), :class => 'start-date'
|
||||||
|
|||||||
11
app/views/estimates/_list.html.erb
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<% if @customer.present? %>
|
||||||
|
|
||||||
|
<% @customer.estimates.order(id: :desc).each do |estimate| %>
|
||||||
|
<div class="row">
|
||||||
|
<b><%= link_to "##{estimate.doc_number}", estimate_path(estimate), target: :_blank %></b> <%= estimate.txn_date %>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<% else %>
|
||||||
|
<p><%=t(:label_no_estimates)%>.</p>
|
||||||
|
<% end %>
|
||||||
4
app/views/estimates/_search.html.erb
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<%= form_tag(estimate_doc_path, :method => "get") do %>
|
||||||
|
<%= text_field_tag :search, params[:search], placeholder: t(:label_search_estimates), :autocomplete => "off" %>
|
||||||
|
<%= submit_tag t(:label_search), :formtarget => "_blank" %>
|
||||||
|
<% end %>
|
||||||
2
app/views/estimates/_sidebar.html.erb
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
<h3><%=t(:label_estimates) %></h3>
|
||||||
|
<%= render :partial => 'estimates/search' %>
|
||||||
11
app/views/invoices/_list.html.erb
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<% if @customer.present? %>
|
||||||
|
|
||||||
|
<% @customer.invoices.order(id: :desc).each do |invoice| %>
|
||||||
|
<div class="row">
|
||||||
|
<b><%= link_to "##{invoice.doc_number}", invoice_path(invoice), target: :_blank %></b> <%= invoice.txn_date %>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<% else %>
|
||||||
|
<p><%=t(:label_no_invoices)%>.</p>
|
||||||
|
<% end %>
|
||||||
14
app/views/issues/_form_hook.html.erb
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<p>
|
||||||
|
<label for="issue_customer"><%= t(:customer) %></label>
|
||||||
|
<%= search_customer %>
|
||||||
|
<%= customer_id %>
|
||||||
|
<%= link_to_function(t(:label_load_customer), "updateIssueFrom('/issues/#{context[:issue].id}/edit.js', this)") %>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<%= select_estimate %>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<%= vehicle %>
|
||||||
|
</p>
|
||||||
35
app/views/issues/_history.html.erb
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<% reply_links = issue.notes_addable? -%>
|
||||||
|
<% for journal in journals %>
|
||||||
|
<div id="change-<%= journal.id %>" class="<%= journal.css_classes %>">
|
||||||
|
<div id="note-<%= journal.indice %>">
|
||||||
|
<div class="contextual">
|
||||||
|
<span class="journal-actions"><%= render_journal_actions(issue, journal, :reply_links => reply_links) %></span>
|
||||||
|
<a href="#note-<%= journal.indice %>" class="journal-link">#<%= journal.indice %></a>
|
||||||
|
</div>
|
||||||
|
<h4>
|
||||||
|
<%= avatar(journal.user, :size => "24") %>
|
||||||
|
<%= authoring journal.created_on, journal.user, :label => :label_updated_time_by %>
|
||||||
|
<%= render_private_notes_indicator(journal) %>
|
||||||
|
</h4>
|
||||||
|
|
||||||
|
<% if journal.details.any? %>
|
||||||
|
<ul class="details">
|
||||||
|
<% details_to_strings(journal.visible_details).each do |string| %>
|
||||||
|
<li><%= string %></li>
|
||||||
|
<% end %>
|
||||||
|
</ul>
|
||||||
|
<% if Setting.thumbnails_enabled? && (thumbnail_attachments = journal_thumbnail_attachments(journal)).any? %>
|
||||||
|
<div class="thumbnails">
|
||||||
|
<% thumbnail_attachments.each do |attachment| %>
|
||||||
|
<div><%= thumbnail_tag(attachment) %></div>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
<%= render_notes(issue, journal, :reply_links => reply_links) unless journal.notes.blank? %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<%= call_hook(:view_issues_history_journal_bottom, { :journal => journal }) %>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<% heads_for_wiki_formatter if User.current.allowed_to?(:edit_issue_notes, issue.project) || User.current.allowed_to?(:edit_own_issue_notes, issue.project) %>
|
||||||
@@ -1,34 +1,34 @@
|
|||||||
<div class="splitcontent">
|
<div class="splitcontent">
|
||||||
<div class="splitcontentleft">
|
<div class="splitcontentleft">
|
||||||
<div class="customer_id attribute">
|
<div class="customer_id attribute">
|
||||||
<div class="label"><span>Customer</span>:</div>
|
<div class="label"><span><%=t(:field_customer)%></span>:</div>
|
||||||
<div class="value"><%= customer %></div>
|
<div class="value"><%= customer %></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="qbo_estimate_id attribute">
|
<div class="estimate_id attribute">
|
||||||
<div class="label"><span>Estimate</span>:</div>
|
<div class="label"><span><%=t(:field_estimate)%></span>:</div>
|
||||||
<div class="value"><%= estimate_link %></div>
|
<div class="value"><%= estimate_link %></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="qbo_invoice_id attribute">
|
<div class="invoice_id attribute">
|
||||||
<div class="label"><span>Invoice</span>:</div>
|
<div class="label"><span><%=t(:field_invoice)%></span>:</div>
|
||||||
<div class="value"><%= invoice_link %></div>
|
<div class="value"><%= invoice_link %></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="splitcontentleft">
|
<div class="splitcontentleft">
|
||||||
<div class="vehicle attribute">
|
<div class="vehicle attribute">
|
||||||
<div class="label"><span>Vehicle</span>:</div>
|
<div class="label"><span><%=t(:field_vehicle)%></span>:</div>
|
||||||
<div class="value"><%= vehicle %></div>
|
<div class="value"><%= vehicle %></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="vehicle_vin attribute">
|
<div class="vehicle_vin attribute">
|
||||||
<div class="label"><span>VIN</span>:</div>
|
<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 class="value"><%=split_vin[0] if split_vin%><b><%=split_vin[1] if split_vin%></b></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="vehicle_notes attribute">
|
<div class="vehicle_notes attribute">
|
||||||
<div class="label"><span>Notes</span>:</div>
|
<div class="label"><span><%=t(:field_notes)%></span>:</div>
|
||||||
<div class="value"><%=notes%></div>
|
<div class="value"><%=notes%></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
<div class="row">
|
|
||||||
<div class="span6 columns">
|
|
||||||
<fieldset>
|
|
||||||
|
|
||||||
<%= form_for @payment do |f| %>
|
|
||||||
|
|
||||||
<div class="clearfix">
|
|
||||||
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:
|
|
||||||
<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:
|
|
||||||
<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:
|
|
||||||
<div class="input">
|
|
||||||
<%= f.number_field :total_amount %>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="actions">
|
|
||||||
<%= f.submit %>
|
|
||||||
</div>
|
|
||||||
<% end %>
|
|
||||||
|
|
||||||
</fieldset>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
<h1>New Payment</h1>
|
|
||||||
<br/>
|
|
||||||
<%= render :partial => 'payments/form' %>
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
<%= flash.now[:error] = "Not Authorized" %>
|
|
||||||
@@ -1 +1 @@
|
|||||||
<b>Last Sync: </b> <%= Qbo.last_sync if Qbo.exists? %>
|
<b><%=t(:label_last_sync)%>: </b> <%= Qbo.last_sync if Qbo.exists? %>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<!--
|
<!--
|
||||||
The MIT License (MIT)
|
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:
|
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,54 +15,63 @@ 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 -->
|
<!-- configure the Intuit object: 'grantUrl' is a URL in your application which kicks off the flow, see below -->
|
||||||
<script>
|
<script>
|
||||||
intuit.ipp.anywhere.setup({menuProxy: '/path/to/blue-dot', grantUrl: '<%= qbo_authenticate_url %>'});
|
intuit.ipp.anywhere.setup({menuProxy: '/path/to/blue-dot', grantUrl: '<%= qbo_authenticate_path %>'});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<table >
|
<table >
|
||||||
<tbody>
|
<tbody>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<th>Intuit QBO OAuth Consumer Key</th>
|
<th><%=t(:label_client_id)%></th>
|
||||||
<td>
|
<td>
|
||||||
<input type="text" style="width:350px" id="settingsOAuthConsumerKey"
|
<input
|
||||||
value="<%= settings['settingsOAuthConsumerKey'] %>"
|
type="text"
|
||||||
name="settings[settingsOAuthConsumerKey]" >
|
style="width:350px"
|
||||||
|
id="settingsOAuthConsumerKey"
|
||||||
|
value="<%= settings['settingsOAuthConsumerKey'] %>"
|
||||||
|
name="settings[settingsOAuthConsumerKey]" >
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<th>Intuit QBO OAuth Consumer Secret</th>
|
<th><%=t(:label_client_secret)%></th>
|
||||||
<td>
|
<td>
|
||||||
<input type="text" style="width:350px" id="settingsOAuthConsumerSecret"
|
<input
|
||||||
value="<%= settings['settingsOAuthConsumerSecret'] %>"
|
type="text"
|
||||||
name="settings[settingsOAuthConsumerSecret]" >
|
style="width:350px"
|
||||||
|
id="settingsOAuthConsumerSecret"
|
||||||
|
value="<%= settings['settingsOAuthConsumerSecret'] %>"
|
||||||
|
name="settings[settingsOAuthConsumerSecret]" >
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<th>Intuit QBO Webhook Token</th>
|
<th><%=t(:label_webhook_token)%></th>
|
||||||
<td>
|
<td>
|
||||||
<input type="text" style="width:350px" id="settingsWebhookToken"
|
<input
|
||||||
value="<%= settings['settingsWebhookToken'] %>"
|
type="text"
|
||||||
name="settings[settingsWebhookToken]" >
|
style="width:350px"
|
||||||
|
id="settingsWebhookToken"
|
||||||
|
value="<%= settings['settingsWebhookToken'] %>"
|
||||||
|
name="settings[settingsWebhookToken]" >
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<th>Token Expires At</th>
|
<th><%=t(:label_oauth_expires)%></th>
|
||||||
<td><%= if Qbo.exists? then Qbo.first.token_expires_at end %>
|
<td><%= if Qbo.exists? then Qbo.first.oauth2_access_token_expires_at end %>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<th>Reconnect Token At</th>
|
<th><%=t(:label_oauth2_refresh_token_expires_at)%></th>
|
||||||
<td><%= if Qbo.exists? then Qbo.first.reconnect_token_at end %>
|
<td><%= if Qbo.exists? then Qbo.first.oauth2_refresh_token_expires_at end %>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<br/>
|
<br/>
|
||||||
Note: You need to authenticate after saving your key and secret above
|
<%=t(:label_oauth_note)%>
|
||||||
<br/>
|
<br/>
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
@@ -73,27 +82,23 @@ Note: You need to authenticate after saving your key and secret above
|
|||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<b>Customer Count:</b> <%= Customer.count%>
|
<b><%=t(:label_customer_count)%>:</b> <%= Customer.count%>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<b>Item Count:</b> <%= QboItem.count %>
|
<b><%=t(:label_employee_count)%>:</b> <%= Employee.count %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<b>Employee Count:</b> <%= QboEmployee.count %>
|
<b><%=t(:label_invoice_count)%>:</b> <%= Invoice.count %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<b>Invoice Count:</b> <%= QboInvoice.count %>
|
<b><%=t(:label_estimate_count)%>:</b> <%= Estimate.count %>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<b>Estimate Count:</b> <%= QboEstimate.count %>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
<div>
|
<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 t(:label_sync_now), qbo_sync_path %>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
6
app/views/qbo/_sidebar.html.erb
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<% if User.current.logged? %>
|
||||||
|
|
||||||
|
<%= render :partial => 'customers/sidebar' %>
|
||||||
|
<%= render :partial => 'estimates/sidebar' %>
|
||||||
|
|
||||||
|
<% end %>
|
||||||
@@ -1 +1 @@
|
|||||||
<%= Customer.count %> Customers - <%= render :partial => 'qbo/last_sync' %>
|
<%= Customer.count %> <%=t(:field_customers)%> - <%= render :partial => 'qbo/last_sync' %>
|
||||||
|
|||||||
@@ -30,4 +30,3 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
|||||||
intuit.ipp.anywhere.setup({menuProxy: '/path/to/blue-dot', grantUrl: '<%= authenticate_vendors_url %>'});
|
intuit.ipp.anywhere.setup({menuProxy: '/path/to/blue-dot', grantUrl: '<%= authenticate_vendors_url %>'});
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
|
|||||||
@@ -1,42 +0,0 @@
|
|||||||
<!--
|
|
||||||
The MIT License (MIT)
|
|
||||||
|
|
||||||
Copyright (c) 2016 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.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<h1> Redmine Quickbooks</h1>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<b>Customer Count:</b> <%= @customer_count.to_s%>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<b>Item Count:</b> <%= @qbo_item_count.to_s %>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<b>Employee Count:</b> <%= @qbo_employee_count.to_s %>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<b>Invoice Count:</b> <%= @qbo_invoice_count.to_s %>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<b>Estimate Count:</b> <%= @qbo_estimate_count.to_s %>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<br/>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<b>Last Sync: </b> <%= Qbo.last_sync if Qbo.exists? %>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
<!--
|
<!--
|
||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (c) 2016 rick barrette
|
Copyright (c) 2024 rick barrette
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
@@ -10,8 +10,4 @@ The above copyright notice and this permission notice shall be included in all c
|
|||||||
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.
|
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.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<body>
|
<h2>QboController#webhook</h2>
|
||||||
|
|
||||||
<h2>QboController#sync</h2>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
@@ -1,38 +1,45 @@
|
|||||||
<table>
|
<div class="issue">
|
||||||
<tbody>
|
<div class="splitcontent">
|
||||||
|
<div class="splitcontentleft">
|
||||||
|
<h4><%=t(:label_details)%>:</h4>
|
||||||
|
|
||||||
<tr>
|
<table>
|
||||||
<th>Customer</th>
|
<tbody>
|
||||||
<td><%= link_to vehicle.customer.name, customer_path(vehicle.customer) %></td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<th>Vehicle</th>
|
<th><%= t(:field_customer)%></th>
|
||||||
<td><%= vehicle.to_s %></td>
|
<td><%= link_to vehicle.customer.name, customer_path(vehicle.customer) %></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<th>VIN</th>
|
<th><%= t(:field_vehicle) %></th>
|
||||||
<td><%= @vin[0] if @vin %><b><%=@vin[1] if @vin%></b></td>
|
<td><%= vehicle.to_s %></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<th>Notes</th>
|
<th><%= t(:field_vin) %></th>
|
||||||
<td><%= vehicle.notes %></td>
|
<td><%= @vin[0] if @vin %><b><%=@vin[1] if @vin%></b></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<th><%= t(:label_trim) %></th>
|
||||||
<th>Issues</th>
|
<td><%= vehicle.doors %> <%=t(:label_door) if vehicle.doors? %> <%= vehicle.trim %></td>
|
||||||
<td><%= vehicle.issues.count %></td>
|
</tr>
|
||||||
</tr>
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
<tr>
|
</div>
|
||||||
<td/>
|
|
||||||
<td>
|
|
||||||
|
|
||||||
<%= button_to "Edit", edit_vehicle_path(vehicle), method: :get%>
|
<div class="splitcontentleft">
|
||||||
<%= button_to "Delete", vehicle, method: :delete, data: {confirm: "You sure?"} %>
|
|
||||||
</td>
|
<h4><%=t(:field_notes)%>:</h4>
|
||||||
</tr>
|
<td><%= vehicle.notes %></td>
|
||||||
</tbody>
|
</tr>
|
||||||
</table>
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="float: right;">
|
||||||
|
<%= 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)} %>
|
||||||
|
</div>
|
||||||
|
|||||||
@@ -4,43 +4,43 @@
|
|||||||
|
|
||||||
<%= form_for @vehicle do |f| %>
|
<%= form_for @vehicle do |f| %>
|
||||||
<div class="clearfix">
|
<div class="clearfix">
|
||||||
Customer:
|
<%=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:
|
|
||||||
<div class="input">
|
<div class="input">
|
||||||
<%= f.number_field :year %>
|
<%= 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>
|
</div>
|
||||||
|
|
||||||
<div class="clearfix">
|
<div class="clearfix">
|
||||||
Make:
|
<%=t(:label_year)%>:
|
||||||
<div class="input">
|
<div class="input">
|
||||||
<%= f.text_field :make %>
|
<%= f.number_field :year, :autocomplete => "off" %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="clearfix">
|
<div class="clearfix">
|
||||||
Model:
|
<%=t(:label_make)%>:
|
||||||
<div class="input">
|
<div class="input">
|
||||||
<%= f.text_field :model %>
|
<%= f.text_field :make, :autocomplete => "off" %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="clearfix">
|
<div class="clearfix">
|
||||||
VIN:
|
<%=t(:label_model)%>:
|
||||||
|
<div class="input">
|
||||||
|
<%= f.text_field :model, :autocomplete => "off" %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="clearfix">
|
||||||
|
<%=t(:field_vin)%>:
|
||||||
<div class="input">
|
<div class="input">
|
||||||
<%= f.text_field :vin , :autofocus => true %>
|
<%= f.text_field :vin , :autofocus => true %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="clearfix">
|
<div class="clearfix">
|
||||||
Notes:
|
<%=t(:field_notes)%>:
|
||||||
<div class="input">
|
<div class="input">
|
||||||
<%= f.text_area :notes, :cols => 60, :rows => 10, :no_label => true %>
|
<%= f.text_area :notes, :cols => 60, :rows => 10, :no_label => true %>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
<br/>
|
<br/>
|
||||||
<%= vehicle.customer %>
|
<%= vehicle.customer %>
|
||||||
<br/>
|
<br/>
|
||||||
<%= vehicle.vin %>
|
<%= vehicle.vin.scan(/.{1,9}/)[0] if vehicle.vin %><b><%=vehicle.vin.scan(/.{1,9}/)[1] if vehicle.vin%></b>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<br/>
|
<br/>
|
||||||
@@ -21,8 +21,8 @@
|
|||||||
<%= will_paginate @vehicles %>
|
<%= will_paginate @vehicles %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p>Matching <%= @vehicles.count %> Vehicles </p>
|
<p><%=t(:label_matching)%> <%=@vehicles.count%> <%=t(:field_vehicles) %> </p>
|
||||||
|
|
||||||
<% else %>
|
<% else %>
|
||||||
<p>There are no vehicles containing the term(s) <%= params[:search] %>.</p>
|
<p><%=t(:label_no_vehicles)%> <%= params[:search] %>.</p>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<%= form_tag(vehicles_path, :method => "get", id: "search-form") do %>
|
<%= form_tag(vehicles_path, :method => "get", id: "search-form") do %>
|
||||||
<%= text_field_tag :search, params[:search], placeholder: "Search Vehicles by VIN" %>
|
<%= text_field_tag :search, params[:search], placeholder: t(:label_search_vin), :autocomplete => "off" %>
|
||||||
<%= submit_tag "Search" %>
|
<%= submit_tag t(:label_search) %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
<h1>Edit Customer Vehicle</h1>
|
<h1><%=t(:label_edit_customer_vehicle)%></h1>
|
||||||
<br/>
|
<br/>
|
||||||
<%= render :partial => 'vehicles/form' %>
|
<%= render :partial => 'vehicles/form' %>
|
||||||
|
|||||||
@@ -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/>
|
<br/>
|
||||||
|
|
||||||
<%= render :partial => 'vehicles/list' %>
|
<%= render :partial => 'vehicles/list' %>
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
<h2>New Customer Vehicle</h2>
|
<h2><%=t(:label_new_vehicle)%></h2>
|
||||||
<br/>
|
<br/>
|
||||||
<%= render :partial => 'vehicles/form' %>
|
<%= render :partial => 'vehicles/form' %>
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
<h2>Vehicle #<%=@vehicle.id%> <span style="float:right"> <%= render :partial => 'customers/search' %> </span> </h2>
|
<h2><%=t(:field_vehicle)%> #<%=@vehicle.id%></h2>
|
||||||
<br/>
|
|
||||||
|
|
||||||
<div style="text-align: left; width:90%;">
|
<%= render :partial => 'vehicles/details', locals: {vehicle: @vehicle} %>
|
||||||
<%= render :partial => 'vehicles/details', locals: {vehicle: @vehicle} %>
|
|
||||||
|
|
||||||
<%= render :partial => 'issues/list_simple', locals: {issues: @vehicle.issues} %>
|
<h3><%=@issues.open.count%> <%=t(:label_open_issues)%></h3>
|
||||||
</div>
|
|
||||||
|
<%= render :partial => 'issues/list_simple', locals: {issues: @issues.open} %>
|
||||||
|
|
||||||
|
<h3><%=@closed_issues.count%> <%=t(:label_closed_issues)%></h3>
|
||||||
|
|
||||||
|
<%= render :partial => 'issues/list_simple', locals: {issues: (@closed_issues)} %>
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
$(function() {
|
$(function() {
|
||||||
$("input#issue_customer_id").on("change", function() {
|
$("input#issue_customer_id").on("change", function() {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: "/filter_vehicles_by_customer",
|
url: "/filter_vehicles_by_customer",
|
||||||
type: "GET",
|
type: "GET",
|
||||||
data: { selected_customer: $("input#issue_customer_id").val() }
|
data: { selected_customer: $("input#issue_customer_id").val() }
|
||||||
});
|
});
|
||||||
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: "/filter_estimates_by_customer",
|
url: "/filter_estimates_by_customer",
|
||||||
type: "GET",
|
type: "GET",
|
||||||
data: { selected_customer: $("input#issue_customer_id").val() }
|
data: { selected_customer: $("input#issue_customer_id").val() }
|
||||||
});
|
});
|
||||||
@@ -15,7 +15,7 @@ $(function() {
|
|||||||
|
|
||||||
$("input#project_customer_id").on("change", function() {
|
$("input#project_customer_id").on("change", function() {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: "/filter_vehicles_by_customer",
|
url: "/filter_vehicles_by_customer",
|
||||||
type: "GET",
|
type: "GET",
|
||||||
data: { selected_customer: $("input#project_customer_id").val() }
|
data: { selected_customer: $("input#project_customer_id").val() }
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#The MIT License (MIT)
|
#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:
|
#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,16 +9,87 @@
|
|||||||
#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.
|
#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
|
# English strings go here for Rails i18n
|
||||||
|
# Usage I18n.t(:label)
|
||||||
en:
|
en:
|
||||||
# my_label: "My label"
|
|
||||||
field_customer: "Customer"
|
field_customer: "Customer"
|
||||||
field_qbo_item: "Item"
|
field_item: "Item"
|
||||||
field_qbo_employee: "Employee"
|
field_employee: "Employee"
|
||||||
field_qbo_invoice: "Invoice"
|
field_invoice: "Invoice"
|
||||||
field_qbo_estimate: "Estimate"
|
field_estimate: "Estimate"
|
||||||
field_vehicles: "Vehicle"
|
field_vehicles: "Vehicles"
|
||||||
field_vehicle: "Vehicle"
|
field_vehicle: "Vehicle"
|
||||||
field_vin: "VIN"
|
field_vin: "VIN"
|
||||||
field_notes: "Notes"
|
field_notes: "Notes"
|
||||||
field_qbo_billed: "Billed"
|
field_billed: "Billed"
|
||||||
label_week: "Week"
|
label_week: "Week"
|
||||||
|
label_search_estimates: "Search Estimates"
|
||||||
|
label_search: "Search"
|
||||||
|
label_estimates: "Estimates"
|
||||||
|
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_amount: "Amount"
|
||||||
|
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"
|
||||||
|
label_no_estimates: "No Estimates"
|
||||||
|
label_no_invoices: "No Invoices"
|
||||||
|
label_invoices: "Invoices"
|
||||||
|
label_load_customer: "Load Customer"
|
||||||
|
label_door: "Door"
|
||||||
|
label_trim: "Trim"
|
||||||
|
label_bill_time: "Bill Time"
|
||||||
|
label_share: "Share"
|
||||||
|
label_sync_now: "Sync Now"
|
||||||
|
label_invoice_404: "Invoice not found"
|
||||||
|
label_estimate_404: "Estimate not found"
|
||||||
|
label_connected: "Successfully connected to Quickbooks"
|
||||||
|
label_error: "Error"
|
||||||
|
label_billed_success: "Successfully Billed "
|
||||||
|
label_billing_error: "Cannot bill without a customer assigned"
|
||||||
|
label_qbo_sync_success: "Successfully synced to Quickbooks"
|
||||||
|
label_hours: "Hours"
|
||||||
|
label_oauth2_refresh_token_expires_at: "Refresh Token Expires At"
|
||||||
|
label_name: "Name"
|
||||||
|
label_appointment: "Add Appointment"
|
||||||
|
label_actions: "Actions"
|
||||||
|
label_create_estimate: "Create Estimate"
|
||||||
|
label_syncing: "Syncing Quickbooks"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#The MIT License (MIT)
|
#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:
|
#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,9 +8,6 @@
|
|||||||
#
|
#
|
||||||
#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.
|
#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.
|
||||||
|
|
||||||
# Main Quickbooks landing page
|
|
||||||
get 'qbo', :to=> 'qbo#index'
|
|
||||||
|
|
||||||
#authentication
|
#authentication
|
||||||
get 'qbo/authenticate', :to => 'qbo#authenticate'
|
get 'qbo/authenticate', :to => 'qbo#authenticate'
|
||||||
get 'qbo/oauth_callback', :to => 'qbo#oauth_callback'
|
get 'qbo/oauth_callback', :to => 'qbo#oauth_callback'
|
||||||
@@ -18,21 +15,20 @@ get 'qbo/oauth_callback', :to => 'qbo#oauth_callback'
|
|||||||
#manual sync
|
#manual sync
|
||||||
get 'qbo/sync', :to => 'qbo#sync'
|
get 'qbo/sync', :to => 'qbo#sync'
|
||||||
|
|
||||||
|
#webhook
|
||||||
|
post 'qbo/webhook', :to => 'qbo#webhook'
|
||||||
|
|
||||||
# Estimate & Invoice PDF
|
# Estimate & Invoice PDF
|
||||||
get 'qbo/estimate/:id', :to => 'estimate#show', as: :estimate
|
get 'estimates/:id', :to => 'estimate#show', as: :estimate
|
||||||
get 'qbo/invoice/:id', :to => 'invoice#show', as: :invoice
|
get 'estimates/doc/', :to => 'estimate#doc', as: :estimate_doc
|
||||||
|
get 'invoices/:id', :to => 'invoice#show', as: :invoice
|
||||||
|
|
||||||
#manual billing
|
#manual billing
|
||||||
get 'qbo/bill/:id', :to => 'qbo#bill', as: :bill
|
get 'bill/:id', :to => 'qbo#bill', as: :bill
|
||||||
|
|
||||||
#customer issue view
|
#customer issue view
|
||||||
get 'customers/view/:token', :to => 'customers#view', as: :view
|
get 'customers/view/:token', :to => 'customers#view', as: :view
|
||||||
|
get 'customers/share/:id', :to => 'customers#share', as: :share
|
||||||
#payments
|
|
||||||
resources :payments
|
|
||||||
|
|
||||||
#webhook
|
|
||||||
post 'qbo/webhook', :to => 'qbo#qbo_webhook'
|
|
||||||
|
|
||||||
#java script routes
|
#java script routes
|
||||||
get 'filter_vehicles_by_customer' => 'customers#filter_vehicles_by_customer'
|
get 'filter_vehicles_by_customer' => 'customers#filter_vehicles_by_customer'
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#The MIT License (MIT)
|
#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:
|
#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.
|
#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
|
def change
|
||||||
create_table :qbos do |t|
|
create_table :qbos do |t|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#The MIT License (MIT)
|
#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:
|
#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.
|
#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
|
def change
|
||||||
create_table :qbo_customers, id: false do |t|
|
create_table :qbo_customers, id: false do |t|
|
||||||
t.integer :id, :options => 'PRIMARY KEY'
|
t.integer :id, :options => 'PRIMARY KEY'
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#The MIT License (MIT)
|
#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:
|
#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.
|
#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
|
def change
|
||||||
add_reference :issues, :qbo_customer, index: true
|
add_reference :issues, :qbo_customer, index: true
|
||||||
add_reference :issues, :qbo_item, index: true
|
add_reference :issues, :qbo_item, index: true
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#The MIT License (MIT)
|
#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:
|
#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.
|
#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
|
def change
|
||||||
create_table :qbo_items, id: false do |t|
|
create_table :qbo_items, id: false do |t|
|
||||||
t.integer :id, :options => 'PRIMARY KEY'
|
t.integer :id, :options => 'PRIMARY KEY'
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#The MIT License (MIT)
|
#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:
|
#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.
|
#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
|
def change
|
||||||
create_table :qbo_employees, id: false do |t|
|
create_table :qbo_employees, id: false do |t|
|
||||||
t.integer :id, :options => 'PRIMARY KEY'
|
t.integer :id, :options => 'PRIMARY KEY'
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#The MIT License (MIT)
|
#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:
|
#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.
|
#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
|
def change
|
||||||
add_reference :users, :qbo_employee, index: true
|
add_reference :users, :qbo_employee, index: true
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#The MIT License (MIT)
|
#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:
|
#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.
|
#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
|
def change
|
||||||
add_column :time_entries, :qbo_billed, :boolean, :default => false
|
add_column :time_entries, :qbo_billed, :boolean, :default => false
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#The MIT License (MIT)
|
#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:
|
#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.
|
#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
|
def change
|
||||||
create_table :qbo_estimates, id: false do |t|
|
create_table :qbo_estimates, id: false do |t|
|
||||||
t.integer :id, :options => 'PRIMARY KEY'
|
t.integer :id, :options => 'PRIMARY KEY'
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#The MIT License (MIT)
|
#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:
|
#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.
|
#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
|
def change
|
||||||
rename_column :qbos, :token, :qb_token
|
rename_column :qbos, :token, :qb_token
|
||||||
rename_column :qbos, :secret, :qb_secret
|
rename_column :qbos, :secret, :qb_secret
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#The MIT License (MIT)
|
#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:
|
#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.
|
#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
|
def change
|
||||||
add_reference :issues, :qbo_estimate, index: true
|
add_reference :issues, :qbo_estimate, index: true
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#The MIT License (MIT)
|
#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:
|
#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.
|
#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
|
def change
|
||||||
create_table :qbo_invoices, id: false do |t|
|
create_table :qbo_invoices, id: false do |t|
|
||||||
t.integer :id, :options => 'PRIMARY KEY'
|
t.integer :id, :options => 'PRIMARY KEY'
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#The MIT License (MIT)
|
#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:
|
#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.
|
#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
|
def change
|
||||||
add_reference :issues, :qbo_invoice, index: true
|
add_reference :issues, :qbo_invoice, index: true
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#The MIT License (MIT)
|
#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:
|
#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.
|
#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
|
def change
|
||||||
create_table :qbo_purchases, id: false do |t|
|
create_table :qbo_purchases, id: false do |t|
|
||||||
t.integer :id, :options => 'PRIMARY KEY'
|
t.integer :id, :options => 'PRIMARY KEY'
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#The MIT License (MIT)
|
#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:
|
#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.
|
#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
|
def change
|
||||||
add_reference :qbo_customers, :qbo_purchase, index: true
|
add_reference :qbo_customers, :qbo_purchase, index: true
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#The MIT License (MIT)
|
#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:
|
#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.
|
#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
|
def change
|
||||||
rename_column :qbo_purchases, :customer_id, :qbo_customer_id
|
rename_column :qbo_purchases, :customer_id, :qbo_customer_id
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#The MIT License (MIT)
|
#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:
|
#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.
|
#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
|
def change
|
||||||
create_table :vehicles do |t|
|
create_table :vehicles do |t|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#The MIT License (MIT)
|
#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:
|
#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.
|
#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
|
def change
|
||||||
add_reference :issues, :vehicles, index: true
|
add_reference :issues, :vehicles, index: true
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#The MIT License (MIT)
|
#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:
|
#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.
|
#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
|
def change
|
||||||
add_column :vehicles, :name, :text
|
add_column :vehicles, :name, :text
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#The MIT License (MIT)
|
#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:
|
#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.
|
#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
|
def change
|
||||||
rename_table :qbo_customers, :customers
|
rename_table :qbo_customers, :customers
|
||||||
rename_column :issues, :qbo_customer_id, :customer_id
|
rename_column :issues, :qbo_customer_id, :customer_id
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#The MIT License (MIT)
|
#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:
|
#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.
|
#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
|
def change
|
||||||
add_column :qbos, :last_sync, :datetime
|
add_column :qbos, :last_sync, :datetime
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#The MIT License (MIT)
|
#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:
|
#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.
|
#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
|
def self.up
|
||||||
create_table :issues_qbo_invoices, :id => false do |t|
|
create_table :issues_qbo_invoices, :id => false do |t|
|
||||||
t.references :issue
|
t.references :issue
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#The MIT License (MIT)
|
#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:
|
#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.
|
#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
|
def change
|
||||||
remove_reference :issues, :qbo_invoice
|
remove_reference :issues, :qbo_invoice
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#The MIT License (MIT)
|
#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:
|
#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.
|
#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
|
def change
|
||||||
create_table :customer_tokens do |t|
|
create_table :customer_tokens do |t|
|
||||||
t.string :token
|
t.string :token
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#The MIT License (MIT)
|
#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:
|
#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.
|
#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
|
def change
|
||||||
add_reference :qbo_invoices, :customer, index: true
|
add_reference :qbo_invoices, :customer, index: true
|
||||||
add_reference :qbo_estimates, :customer, index: true
|
add_reference :qbo_estimates, :customer, index: true
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#The MIT License (MIT)
|
#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:
|
#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.
|
#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
|
def change
|
||||||
add_reference :projects, :customer, index: true
|
add_reference :projects, :customer, index: true
|
||||||
add_reference :projects, :vehicle, index: true
|
add_reference :projects, :vehicle, index: true
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#The License
|
#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.
|
#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.
|
#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
|
def change
|
||||||
create_table :line_items do |t|
|
create_table :line_items do |t|
|
||||||
t.integer :item_id
|
t.integer :item_id
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#The MIT License (MIT)
|
#The MIT License (MIT)
|
||||||
#
|
#
|
||||||
#Copyright (c) 2019 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:
|
#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.
|
#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
|
class AddCustomersPhoneNumber < ActiveRecord::Migration[5.1]
|
||||||
def change
|
def change
|
||||||
add_column :customers, :phone_number, :string
|
add_column :customers, :phone_number, :string
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#The MIT License (MIT)
|
#The MIT License (MIT)
|
||||||
#
|
#
|
||||||
#Copyright (c) 2019 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:
|
#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.
|
#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
|
class AddCustomersMobilePhoneNumber < ActiveRecord::Migration[5.1]
|
||||||
def change
|
def change
|
||||||
add_column :customers, :mobile_phone_number, :string
|
add_column :customers, :mobile_phone_number, :string
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#The MIT License (MIT)
|
#The MIT License (MIT)
|
||||||
#
|
#
|
||||||
#Copyright (c) 2020 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:
|
#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.
|
#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 UpdateQbosTypes < ActiveRecord::Migration
|
class UpdateQbosTypes < ActiveRecord::Migration[5.1]
|
||||||
|
|
||||||
def change
|
def change
|
||||||
change_column :qbos, :qb_token, :text
|
change_column :qbos, :qb_token, :text
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#The MIT License (MIT)
|
#The MIT License (MIT)
|
||||||
#
|
#
|
||||||
#Copyright (c) 2020 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:
|
#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.
|
#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
|
class UpdateQbosToken < ActiveRecord::Migration[5.1]
|
||||||
|
|
||||||
def change
|
def change
|
||||||
add_column :qbos, :token, :text
|
add_column :qbos, :token, :text
|
||||||
|
|||||||
18
db/migrate/031_remove_qbos_keys.rb
Normal 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
|
||||||
55
db/migrate/032_add_txn_dates.rb
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
#The MIT License (MIT)
|
||||||
|
#
|
||||||
|
#Copyright (c) 2024 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 AddTxnDates < ActiveRecord::Migration[5.1]
|
||||||
|
|
||||||
|
def change
|
||||||
|
begin
|
||||||
|
add_column :qbo_invoices, :txn_date, :date
|
||||||
|
add_column :qbo_estimates, :txn_date, :date
|
||||||
|
|
||||||
|
reversible do |direction|
|
||||||
|
direction.up {
|
||||||
|
break unless Qbo.first
|
||||||
|
|
||||||
|
QboEstimate.reset_column_information
|
||||||
|
QboInvoice.reset_column_information
|
||||||
|
|
||||||
|
say "Sync Estimates"
|
||||||
|
|
||||||
|
QboEstimate.sync
|
||||||
|
|
||||||
|
say "Sync Invoices"
|
||||||
|
|
||||||
|
qbo = Qbo.first
|
||||||
|
invoices = qbo.perform_authenticated_request do |access_token|
|
||||||
|
service = Quickbooks::Service::Invoice.new(:company_id => qbo.realm_id, :access_token => access_token)
|
||||||
|
service.all
|
||||||
|
end
|
||||||
|
|
||||||
|
return unless invoices
|
||||||
|
|
||||||
|
invoices.each { |invoice|
|
||||||
|
# Load the invoice into the database
|
||||||
|
qbo_invoice = QboInvoice.find_or_create_by(id: invoice.id)
|
||||||
|
qbo_invoice.doc_number = invoice.doc_number
|
||||||
|
qbo_invoice.id = invoice.id
|
||||||
|
qbo_invoice.customer_id = invoice.customer_ref
|
||||||
|
qbo_invoice.txn_date = invoice.txn_date
|
||||||
|
qbo_invoice.save!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
rescue
|
||||||
|
logger.error "AddTxnDates Failed"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||