killbill-avatax 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +39 -0
  4. data/Rakefile +37 -0
  5. data/app/assets/javascripts/application.js +24 -0
  6. data/app/assets/javascripts/avatax/avatax.js +7 -0
  7. data/app/assets/stylesheets/application.css +19 -0
  8. data/app/assets/stylesheets/avatax/avatax.css +6 -0
  9. data/app/assets/stylesheets/bootstrap_and_overrides.css +17 -0
  10. data/app/controllers/avatax/configuration_controller.rb +142 -0
  11. data/app/controllers/avatax/engine_controller.rb +18 -0
  12. data/app/helpers/avatax/application_helper.rb +4 -0
  13. data/app/views/avatax/configuration/_exemptions_form.html.erb +20 -0
  14. data/app/views/avatax/configuration/_exemptions_table.html.erb +34 -0
  15. data/app/views/avatax/configuration/_plugin_form.html.erb +43 -0
  16. data/app/views/avatax/configuration/_products_form.html.erb +20 -0
  17. data/app/views/avatax/configuration/_products_table.html.erb +34 -0
  18. data/app/views/avatax/configuration/index.html.erb +30 -0
  19. data/app/views/avatax/configuration/plugin_configuration.html.erb +7 -0
  20. data/app/views/avatax/configuration/set_exemption.html.erb +10 -0
  21. data/app/views/avatax/configuration/set_tax_code.html.erb +10 -0
  22. data/app/views/avatax/layouts/avatax_application.html.erb +31 -0
  23. data/config/routes.rb +20 -0
  24. data/lib/avatax.rb +22 -0
  25. data/lib/avatax/client.rb +63 -0
  26. data/lib/avatax/engine.rb +19 -0
  27. data/lib/avatax/version.rb +3 -0
  28. data/lib/tasks/avatax_tasks.rake +4 -0
  29. data/test/avatax_test.rb +7 -0
  30. data/test/dummy/README.rdoc +28 -0
  31. data/test/dummy/Rakefile +6 -0
  32. data/test/dummy/app/controllers/application_controller.rb +5 -0
  33. data/test/dummy/app/helpers/application_helper.rb +2 -0
  34. data/test/dummy/bin/bundle +3 -0
  35. data/test/dummy/bin/rails +4 -0
  36. data/test/dummy/bin/rake +4 -0
  37. data/test/dummy/bin/setup +29 -0
  38. data/test/dummy/config.ru +4 -0
  39. data/test/dummy/config/application.rb +32 -0
  40. data/test/dummy/config/boot.rb +5 -0
  41. data/test/dummy/config/database.yml +23 -0
  42. data/test/dummy/config/environment.rb +5 -0
  43. data/test/dummy/config/environments/development.rb +41 -0
  44. data/test/dummy/config/environments/production.rb +79 -0
  45. data/test/dummy/config/environments/test.rb +42 -0
  46. data/test/dummy/config/initializers/assets.rb +11 -0
  47. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  48. data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
  49. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  50. data/test/dummy/config/initializers/inflections.rb +16 -0
  51. data/test/dummy/config/initializers/killbill_client.rb +3 -0
  52. data/test/dummy/config/initializers/mime_types.rb +4 -0
  53. data/test/dummy/config/initializers/session_store.rb +3 -0
  54. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  55. data/test/dummy/config/locales/en.yml +23 -0
  56. data/test/dummy/config/routes.rb +4 -0
  57. data/test/dummy/config/secrets.yml +22 -0
  58. data/test/integration/navigation_test.rb +8 -0
  59. data/test/test_helper.rb +21 -0
  60. metadata +411 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 3285db47eceafe1937d8442d8805988a36c4af21
4
+ data.tar.gz: bd8fe2e0c1cfbf658d4d669ee7ea6f1dc89669bb
5
+ SHA512:
6
+ metadata.gz: 6283e0e3bd7962ccb15e80879273222733b043799e458883d0f8a8797465af23b62b5efe28ece5f387a125f1d34b37763f07ffd796950e1ed5cf3fa0a4b13a35
7
+ data.tar.gz: 8dff593076931351517f0b5deb345b0b94b9b7b17c02f11cdd16c3cf50b485b8d154bed74f5636da7e7a7df9de13e18e8a827ef2778e67670c0cb4527c07bf19
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2015 The Billing Project, LLC
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,39 @@
1
+
2
+ Overview
3
+ ========
4
+
5
+ This Rails mountable engine allows you to manage your Avatax integration in Kill Bill.
6
+
7
+ * See [killbill/killbill-avatax-plugin](https://github.com/killbill/killbill-avatax-plugin) to get started with the Avatax plugin.
8
+ * See [killbill-admin-ui-standalone](https://github.com/killbill/killbill-admin-ui-standalone) to get start with the Kill Bill Admin UI.
9
+
10
+ Functionality
11
+ -------------
12
+
13
+ This app lets you:
14
+
15
+ * configure tax codes associated with products in your catalog
16
+ * set tax exemption codes on Kill Bill accounts
17
+ * configure your Avatax credentials
18
+
19
+ Getting Started
20
+ ---------------
21
+
22
+ You can run this locally by using the test/dummy app provided.
23
+
24
+ To do so, specify your Kill Bill server url, api key and secret in ```test/dummy/config/initializers/killbill_client.rb```:
25
+
26
+ ```
27
+ KillBillClient.url = 'http://127.0.0.1:8080/'
28
+ KillBillClient.api_key = 'bob'
29
+ KillBillClient.api_secret = 'lazar'
30
+ ```
31
+
32
+ Then, simply run:
33
+
34
+ ```
35
+ bundle install
36
+ export RAILS_ENV=development
37
+ cd test/dummy
38
+ rails server
39
+ ```
data/Rakefile ADDED
@@ -0,0 +1,37 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'Avatax'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.rdoc')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
18
+ load 'rails/tasks/engine.rake'
19
+
20
+
21
+ load 'rails/tasks/statistics.rake'
22
+
23
+
24
+
25
+ Bundler::GemHelper.install_tasks
26
+
27
+ require 'rake/testtask'
28
+
29
+ Rake::TestTask.new(:test) do |t|
30
+ t.libs << 'lib'
31
+ t.libs << 'test'
32
+ t.pattern = 'test/**/*_test.rb'
33
+ t.verbose = false
34
+ end
35
+
36
+
37
+ task default: :test
@@ -0,0 +1,24 @@
1
+ // This is a manifest file that'll be compiled into application.js, which will include all the files
2
+ // listed below.
3
+ //
4
+ // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5
+ // or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
6
+ //
7
+ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8
+ // compiled file.
9
+ //
10
+ // Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
11
+ // about supported directives.
12
+ //
13
+ //= require js-routes
14
+ //= require moment
15
+ //= require spin
16
+ //= require jquery
17
+ //= require jquery_ujs
18
+ //= require twitter/bootstrap
19
+ //= require dataTables/jquery.dataTables
20
+ //= require dataTables/bootstrap/3/jquery.dataTables.bootstrap
21
+ //= require d3
22
+ //= require bootstrap-datepicker
23
+ //= require jquery.spin
24
+ //= require avatax/avatax
@@ -0,0 +1,7 @@
1
+ // This is a manifest file that'll be compiled into including all the files listed below.
2
+ // Add new JavaScript/Coffee code in separate files in this directory and they'll automatically
3
+ // be included in the compiled file accessible from http://example.com/assets/application.js
4
+ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
5
+ // the compiled file.
6
+ //
7
+ //= require_tree .
@@ -0,0 +1,19 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9
+ * compiled file so the styles you add here take precedence over styles defined in any styles
10
+ * defined in the other CSS/SCSS files in this directory. It is generally better to create a new
11
+ * file per style scope.
12
+ *
13
+ *= require_self
14
+ *= require bootstrap-datepicker3
15
+ *= require dataTables/jquery.dataTables
16
+ *= require dataTables/bootstrap/3/jquery.dataTables.bootstrap
17
+ *= require bootstrap_and_overrides
18
+ *= require avatax/avatax
19
+ */
@@ -0,0 +1,6 @@
1
+ /*
2
+ * This is a manifest file that'll automatically include all the stylesheets available in this directory
3
+ * and any sub-directories. You're free to add application-wide styles to this file and they'll appear at
4
+ * the top of the compiled file, but it's generally better to create a new file per style scope.
5
+ *= require_tree .
6
+ */
@@ -0,0 +1,17 @@
1
+ /*
2
+ *= require twitter-bootstrap-static/bootstrap
3
+ *
4
+ * Use Font Awesome icons (default)
5
+ * To use Glyphicons sprites instead of Font Awesome, replace with "require twitter-bootstrap-static/sprites"
6
+ *= require twitter-bootstrap-static/fontawesome
7
+ */
8
+
9
+ /* Override Bootstrap 3 font locations */
10
+ @font-face {
11
+ font-family: 'Glyphicons Halflings';
12
+ src: url('../assets/glyphicons-halflings-regular.eot');
13
+ src: url('../assets/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'),
14
+ url('../assets/glyphicons-halflings-regular.woff') format('woff'),
15
+ url('../assets/glyphicons-halflings-regular.ttf') format('truetype'),
16
+ url('../assets/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg');
17
+ }
@@ -0,0 +1,142 @@
1
+ require 'avatax/client'
2
+
3
+ module Avatax
4
+ class ConfigurationController < EngineController
5
+
6
+ def index
7
+ @tax_codes = ::Killbill::Avatax::AvataxClient.get_tax_codes(options_for_klient)
8
+ @exemptions = exempt_accounts
9
+ end
10
+
11
+ #
12
+ # Tax Codes
13
+ #
14
+
15
+ def set_tax_code
16
+ @products = KillBillClient::Model::Catalog.simple_catalog(options_for_klient).products.map(&:name)
17
+ end
18
+
19
+ def do_set_tax_code
20
+ ::Killbill::Avatax::AvataxClient.set_tax_code(params.require(:product_name),
21
+ params.require(:tax_code),
22
+ options_for_klient[:username],
23
+ params[:reason],
24
+ params[:comment],
25
+ options_for_klient)
26
+
27
+ flash[:notice] = 'Tax code successfully saved'
28
+ redirect_to :action => :index
29
+ end
30
+
31
+ def remove_tax_code
32
+ ::Killbill::Avatax::AvataxClient.remove_tax_code(params.require(:product_name),
33
+ options_for_klient[:username],
34
+ params[:reason],
35
+ params[:comment],
36
+ options_for_klient)
37
+
38
+ flash[:notice] = 'Tax code successfully removed'
39
+ redirect_to :action => :index
40
+ end
41
+
42
+ #
43
+ # Exemptions
44
+ #
45
+
46
+ def set_exemption
47
+ end
48
+
49
+ def do_set_exemption
50
+ ::Killbill::Avatax::AvataxClient.set_exemption(params.require(:account_id),
51
+ params.require(:customer_usage_type),
52
+ options_for_klient[:username],
53
+ params[:reason],
54
+ params[:comment],
55
+ options_for_klient)
56
+
57
+ flash[:notice] = 'Exemption successfully saved'
58
+ redirect_to :action => :index
59
+ end
60
+
61
+ def remove_exemption
62
+ ::Killbill::Avatax::AvataxClient.remove_exemption(params.require(:account_id),
63
+ options_for_klient[:username],
64
+ params[:reason],
65
+ params[:comment],
66
+ options_for_klient)
67
+
68
+ flash[:notice] = 'Exemption successfully removed'
69
+ redirect_to :action => :index
70
+ end
71
+
72
+ #
73
+ # Settings
74
+ #
75
+
76
+ def plugin_configuration
77
+ @configuration = {}
78
+
79
+ config = KillBillClient::Model::Tenant.get_tenant_plugin_config('killbill-avatax', options_for_klient)
80
+ return if config.values.empty?
81
+
82
+ config.values.first.split.each do |property|
83
+ k, v = property.split('=')
84
+ case k
85
+ when 'org.killbill.billing.plugin.avatax.url'
86
+ @configuration[:test] = avatax_url(true) == v
87
+ when 'org.killbill.billing.plugin.avatax.accountNumber'
88
+ @configuration[:account_number] = v
89
+ when 'org.killbill.billing.plugin.avatax.licenseKey'
90
+ @configuration[:license_key] = v
91
+ when 'org.killbill.billing.plugin.avatax.companyCode'
92
+ @configuration[:company_code] = v
93
+ when 'org.killbill.billing.plugin.avatax.commitDocuments'
94
+ @configuration[:commit_documents] = v == 'true'
95
+ end
96
+ end
97
+ end
98
+
99
+ def update_plugin_configuration
100
+ plugin_config = "org.killbill.billing.plugin.avatax.url=#{avatax_url(params[:test] == '1')}
101
+ org.killbill.billing.plugin.avatax.accountNumber=#{params.require(:account_number)}
102
+ org.killbill.billing.plugin.avatax.licenseKey=#{params.require(:license_key)}
103
+ org.killbill.billing.plugin.avatax.companyCode=#{params[:company_code]}
104
+ org.killbill.billing.plugin.avatax.commitDocuments=#{params[:commit_documents] == '1'}"
105
+
106
+ KillBillClient::Model::Tenant.upload_tenant_plugin_config('killbill-avatax',
107
+ plugin_config,
108
+ options_for_klient[:username],
109
+ params[:reason],
110
+ params[:comment],
111
+ options_for_klient)
112
+
113
+ flash[:notice] = 'Configuration successfully saved'
114
+ redirect_to :action => :index
115
+ end
116
+
117
+ private
118
+
119
+ def avatax_url(test)
120
+ "https://#{test ? 'development' : 'avatax'}.avalara.net"
121
+ end
122
+
123
+ def exempt_accounts(offset = 0, limit = 100)
124
+ custom_field_value = 'customerUsageType'
125
+
126
+ KillBillClient::Model::CustomField.find_in_batches_by_search_key(custom_field_value, offset, limit, options_for_klient)
127
+ .select { |cf| cf.name == custom_field_value && cf.object_type == 'ACCOUNT' }
128
+ .map { |cf| {:account_id => cf.object_id, :customer_usage_type => cf.value} }
129
+ end
130
+
131
+ def options_for_klient
132
+ user = current_tenant_user
133
+ {
134
+ :username => user[:username],
135
+ :password => user[:password],
136
+ :session_id => user[:session_id],
137
+ :api_key => user[:api_key],
138
+ :api_secret => user[:api_secret]
139
+ }
140
+ end
141
+ end
142
+ end
@@ -0,0 +1,18 @@
1
+ module Avatax
2
+ class EngineController < ApplicationController
3
+
4
+ layout :get_layout
5
+
6
+ def get_layout
7
+ layout ||= Avatax.config[:layout]
8
+ end
9
+
10
+ def current_tenant_user
11
+ # If the rails application on which that engine is mounted defines such method (Devise), we extract the current user,
12
+ # if not we default to nil, and serve our static mock configuration
13
+ user = current_user if respond_to?(:current_user)
14
+ Avatax.current_tenant_user.call(session, user)
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,4 @@
1
+ module Avatax
2
+ module ApplicationHelper
3
+ end
4
+ end
@@ -0,0 +1,20 @@
1
+ <%= form_tag do_set_exemption_configuration_path, :class => 'form-horizontal' do %>
2
+ <div class="form-group">
3
+ <%= label_tag :account_id, 'Account ID', :class => 'col-sm-2 control-label' %>
4
+
5
+ <div class="col-sm-10">
6
+ <%= text_field_tag :account_id, nil, :class => 'form-control' %>
7
+ </div>
8
+ </div>
9
+ <div class="form-group">
10
+ <%= label_tag :customer_usage_type, 'Customer Usage Type', :class => 'col-sm-2 control-label' %>
11
+ <div class="col-sm-10">
12
+ <%= text_field_tag :customer_usage_type, nil, :class => 'form-control' %>
13
+ </div>
14
+ </div>
15
+ <div class="form-group">
16
+ <div class="col-sm-offset-2 col-sm-10">
17
+ <%= submit_tag 'Save', :class => 'btn btn-default' %>
18
+ </div>
19
+ </div>
20
+ <% end %>
@@ -0,0 +1,34 @@
1
+ <table id="exemptions-table" class="table table-condensed table-striped mobile-data">
2
+ <thead>
3
+ <tr>
4
+ <th>Account ID</th>
5
+ <th>Customer Usage Type</th>
6
+ <th></th>
7
+ </tr>
8
+ </thead>
9
+ <tbody>
10
+ <% exemptions.each do |exemption| %>
11
+ <tr>
12
+ <td><%= exemption[:account_id] %></td>
13
+ <td><%= exemption[:customer_usage_type] %></td>
14
+ <td>
15
+ <%= link_to '<i class="fa fa-times"></i>'.html_safe, remove_exemption_configuration_path(:account_id => exemption[:account_id]), :method => :delete %>
16
+ </td>
17
+ </tr>
18
+ <% end %>
19
+ </tbody>
20
+ </table>
21
+
22
+ <%= javascript_tag do %>
23
+ $(document).ready(function() {
24
+ $('#exemptions-table').dataTable({
25
+ "dom": "t",
26
+ "paging": false,
27
+ "columns": [
28
+ null,
29
+ null,
30
+ { "orderable": false }
31
+ ]
32
+ });
33
+ });
34
+ <% end %>
@@ -0,0 +1,43 @@
1
+ <%= form_tag update_plugin_configuration_path, :class => 'form-horizontal' do %>
2
+ <div class="form-group">
3
+ <%= label_tag :account_number, 'Account number', :class => 'col-sm-2 control-label' %>
4
+ <div class="col-sm-10">
5
+ <%= text_field_tag :account_number, @configuration[:account_number], :class => 'form-control' %>
6
+ </div>
7
+ </div>
8
+ <div class="form-group">
9
+ <%= label_tag :license_key, 'License key', :class => 'col-sm-2 control-label' %>
10
+ <div class="col-sm-10">
11
+ <%= text_field_tag :license_key, @configuration[:license_key], :class => 'form-control' %>
12
+ </div>
13
+ </div>
14
+ <div class="form-group">
15
+ <%= label_tag :company_code, 'Company code', :class => 'col-sm-2 control-label' %>
16
+ <div class="col-sm-10">
17
+ <%= text_field_tag :company_code, @configuration[:company_code], :class => 'form-control' %>
18
+ </div>
19
+ </div>
20
+ <div class="form-group">
21
+ <div class="col-sm-offset-2 col-sm-10">
22
+ <div class="checkbox">
23
+ <%= label_tag :commit_documents, 'Commit documents', :class => 'control-label' do %>
24
+ <%= check_box_tag :commit_documents, '1', @configuration[:commit_documents] %>Commit documents?
25
+ <% end %>
26
+ </div>
27
+ </div>
28
+ </div>
29
+ <div class="form-group">
30
+ <div class="col-sm-offset-2 col-sm-10">
31
+ <div class="checkbox">
32
+ <%= label_tag :test, 'Test mode', :class => 'control-label' do %>
33
+ <%= check_box_tag :test, '1', @configuration[:test] %>Test mode?
34
+ <% end %>
35
+ </div>
36
+ </div>
37
+ </div>
38
+ <div class="form-group">
39
+ <div class="col-sm-offset-2 col-sm-10">
40
+ <%= submit_tag 'Save', :class => 'btn btn-default' %>
41
+ </div>
42
+ </div>
43
+ <% end %>