openstax_salesforce 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +91 -0
- data/Rakefile +30 -0
- data/app/controllers/openstax/salesforce/application_controller.rb +5 -0
- data/app/controllers/openstax/salesforce/settings_controller.rb +20 -0
- data/app/helpers/openstax/salesforce/application_helper.rb +11 -0
- data/app/models/openstax/salesforce/user.rb +25 -0
- data/app/models/user.rb +25 -0
- data/app/views/openstax/salesforce/settings/show.html.erb +33 -0
- data/config/initializers/omniauth.rb +8 -0
- data/config/initializers/openstax_salesforce.rb +48 -0
- data/config/routes.rb +11 -0
- data/db/migrate/0_install_openstax_salesforce.rb +12 -0
- data/lib/openstax/salesforce/active_force.rb +34 -0
- data/lib/openstax/salesforce/client.rb +24 -0
- data/lib/openstax/salesforce/engine.rb +9 -0
- data/lib/openstax/salesforce/remote/book.rb +7 -0
- data/lib/openstax/salesforce/remote/contact.rb +18 -0
- data/lib/openstax/salesforce/remote/lead.rb +22 -0
- data/lib/openstax/salesforce/remote/school.rb +7 -0
- data/lib/openstax/salesforce/spec_helpers/salesforce_proxy.rb +99 -0
- data/lib/openstax/salesforce/spec_helpers.rb +58 -0
- data/lib/openstax/salesforce/user_missing.rb +3 -0
- data/lib/openstax/salesforce/version.rb +5 -0
- data/lib/openstax_salesforce.rb +58 -0
- data/lib/tasks/openstax_salesforce_tasks.rake +47 -0
- data/spec/client_spec.rb +10 -0
- data/spec/dummy/README.md +28 -0
- data/spec/dummy/Rakefile +6 -0
- data/spec/dummy/app/assets/javascripts/application.js +13 -0
- data/spec/dummy/app/assets/stylesheets/application.css +15 -0
- data/spec/dummy/app/controllers/application_controller.rb +5 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/bin/bundle +3 -0
- data/spec/dummy/bin/rails +4 -0
- data/spec/dummy/bin/rake +4 -0
- data/spec/dummy/bin/setup +29 -0
- data/spec/dummy/config/application.rb +26 -0
- data/spec/dummy/config/boot.rb +5 -0
- data/spec/dummy/config/database.yml +25 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +41 -0
- data/spec/dummy/config/environments/production.rb +79 -0
- data/spec/dummy/config/environments/test.rb +42 -0
- data/spec/dummy/config/initializers/assets.rb +11 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy/config/initializers/inflections.rb +16 -0
- data/spec/dummy/config/initializers/mime_types.rb +4 -0
- data/spec/dummy/config/initializers/session_store.rb +3 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +23 -0
- data/spec/dummy/config/routes.rb +3 -0
- data/spec/dummy/config/secrets.yml +22 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/db/schema.rb +26 -0
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/log/test.log +50 -0
- data/spec/dummy/public/404.html +67 -0
- data/spec/dummy/public/422.html +67 -0
- data/spec/dummy/public/500.html +66 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/openstax/salesforce/spec_helpers_spec.rb +31 -0
- data/spec/rails_helper.rb +55 -0
- data/spec/spec_helper.rb +86 -0
- metadata +292 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 66066f14c2a63bbba0e2e92314c1841447a8bb58
|
4
|
+
data.tar.gz: 0188ff2c949728a8c47f4305b14ea57bc4324f71
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 31776fad63147b4f3d8931930679c5665c2141cd61b78e5b21a0d91403fdcb7df3207e8237c49594501fc6cb6b96cb1acbb60519f21e384f1fd888376c92d6b7
|
7
|
+
data.tar.gz: ef1ffb3e25b322aabf3fa2d3972baa9e5589f09c9f2721e888eb935bc3fca601c89d15c23b4b88f43a88338b52138d29aaacbcae23539b86ba77327b27523437
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2017 JP Slavinsky
|
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,91 @@
|
|
1
|
+
# OpenStax::Salesforce
|
2
|
+
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/openstax_salesforce.svg)](http://badge.fury.io/rb/fine_print)
|
4
|
+
[![Build Status](https://travis-ci.org/openstax/openstax_salesforce.svg?branch=master)](https://travis-ci.org/openstax/openstax_salesforce)
|
5
|
+
[![Code Climate](https://codeclimate.com/github/openstax/openstax_salesforce/badges/gpa.svg)](https://codeclimate.com/github/openstax/openstax_salesforce)
|
6
|
+
|
7
|
+
OpenStax::Salesforce is a Rails engine used by OpenStax projects to communicate with the OpenStax Salesforce instance.
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
Add these line to your application's Gemfile:
|
12
|
+
|
13
|
+
```rb
|
14
|
+
gem 'openstax_salesforce'
|
15
|
+
|
16
|
+
# ActiveForce fork that supports Ruby >= 2.1 and stubbable stdout
|
17
|
+
gem 'active_force', git: 'https://github.com/openstax/active_force', ref: '7caac17'
|
18
|
+
```
|
19
|
+
|
20
|
+
And then execute:
|
21
|
+
|
22
|
+
```sh
|
23
|
+
$ bundle
|
24
|
+
```
|
25
|
+
|
26
|
+
Or install it yourself:
|
27
|
+
|
28
|
+
```sh
|
29
|
+
$ gem install openstax_salesforce
|
30
|
+
```
|
31
|
+
|
32
|
+
Then execute the following command to copy the necessary migration and the initializer to your application:
|
33
|
+
|
34
|
+
```sh
|
35
|
+
$ rake openstax_salesforce:install
|
36
|
+
```
|
37
|
+
|
38
|
+
And then migrate your database:
|
39
|
+
|
40
|
+
```sh
|
41
|
+
$ rake db:migrate
|
42
|
+
```
|
43
|
+
|
44
|
+
Also add OpenStax::Salesforce to your application's routes:
|
45
|
+
|
46
|
+
```rb
|
47
|
+
mount OpenStax::Salesforce::Engine, at: "/salesforce"
|
48
|
+
OpenStax::Salesforce.set_top_level_routes(self)
|
49
|
+
```
|
50
|
+
|
51
|
+
The `set_top_level_routes` should be called at the top level inside `routes.rb`. It adds oauth callback
|
52
|
+
routes at the top level.
|
53
|
+
|
54
|
+
And provide a link on your site for administrators to access the engine.
|
55
|
+
|
56
|
+
```erb
|
57
|
+
<%= link_to 'Salesforce Setup', openstax_salesforce_path %>
|
58
|
+
```
|
59
|
+
|
60
|
+
## Configuration
|
61
|
+
|
62
|
+
After installation, the initializer for OpenStax::Salesforce will be located under
|
63
|
+
`config/initializers/openstax_salesforce.rb`. Make sure to configure it to suit
|
64
|
+
your needs. Pay particular attention to `authenticate_admin_proc`,
|
65
|
+
as you will be unable to access the setup pages until this proc is setup to return
|
66
|
+
`true` for your admins.
|
67
|
+
|
68
|
+
## Testing
|
69
|
+
|
70
|
+
From the gem's main folder, run `bundle install`,
|
71
|
+
`bundle exec rake db:migrate` and then
|
72
|
+
`bundle exec rake` to run all the specs.
|
73
|
+
|
74
|
+
## Specs in Parent App
|
75
|
+
|
76
|
+
There's a helper you can include in your parent app's salesforce specs. It isn't automatically
|
77
|
+
required by this engine, so you have to do it manually in your spec:
|
78
|
+
|
79
|
+
```ruby
|
80
|
+
require 'openstax/salesforce/spec_helper'
|
81
|
+
```
|
82
|
+
|
83
|
+
## Contributing
|
84
|
+
|
85
|
+
1. Fork it
|
86
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
87
|
+
3. Create specs for your feature
|
88
|
+
4. Ensure that all specs pass
|
89
|
+
5. Commit your changes (`git commit -am 'Add some feature'`)
|
90
|
+
6. Push to the branch (`git push origin my-new-feature`)
|
91
|
+
7. Create new pull request
|
data/Rakefile
ADDED
@@ -0,0 +1,30 @@
|
|
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 = 'OpenStax::Salesforce'
|
12
|
+
rdoc.options << '--line-numbers'
|
13
|
+
rdoc.rdoc_files.include('README.md')
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
+
end
|
16
|
+
|
17
|
+
APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
|
18
|
+
load 'rails/tasks/engine.rake'
|
19
|
+
|
20
|
+
load 'rails/tasks/statistics.rake'
|
21
|
+
|
22
|
+
Bundler::GemHelper.install_tasks
|
23
|
+
|
24
|
+
require 'rspec/core'
|
25
|
+
require 'rspec/core/rake_task'
|
26
|
+
|
27
|
+
desc 'Run all specs in spec directory (excluding plugin specs)'
|
28
|
+
RSpec::Core::RakeTask.new(:spec => 'app:db:test:prepare')
|
29
|
+
|
30
|
+
task :default => :spec
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module OpenStax::Salesforce
|
2
|
+
class SettingsController < OpenStax::Salesforce::ApplicationController
|
3
|
+
layout OpenStax::Salesforce.configuration.layout
|
4
|
+
|
5
|
+
def show
|
6
|
+
end
|
7
|
+
|
8
|
+
def callback
|
9
|
+
OpenStax::Salesforce::User.save_from_omniauth!(env["omniauth.auth"])
|
10
|
+
redirect_to root_path
|
11
|
+
end
|
12
|
+
|
13
|
+
def destroy_user
|
14
|
+
OpenStax::Salesforce::User.destroy_all
|
15
|
+
ActiveForce.clear_sfdc_client! # since user is now gone, any client invalid
|
16
|
+
redirect_to root_path
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module OpenStax::Salesforce
|
2
|
+
class User < ActiveRecord::Base
|
3
|
+
validates :uid, presence: true
|
4
|
+
validates :oauth_token, presence: true
|
5
|
+
validates :refresh_token, presence: true
|
6
|
+
validates :instance_url, presence: true
|
7
|
+
|
8
|
+
after_save :ensure_only_one_record
|
9
|
+
|
10
|
+
def self.save_from_omniauth!(auth)
|
11
|
+
where(auth.slice(:uid).permit!).first_or_initialize.tap do |user|
|
12
|
+
user.uid = auth.uid
|
13
|
+
user.name = auth.info.name
|
14
|
+
user.oauth_token = auth.credentials.token
|
15
|
+
user.refresh_token = auth.credentials.refresh_token
|
16
|
+
user.instance_url = auth.credentials.instance_url
|
17
|
+
user.save!
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def ensure_only_one_record
|
22
|
+
self.class.where{id != self.id}.destroy_all
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/app/models/user.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
module OpenStax::Salesforce
|
2
|
+
class User < ActiveRecord::Base
|
3
|
+
validates :uid, presence: true
|
4
|
+
validates :oauth_token, presence: true
|
5
|
+
validates :refresh_token, presence: true
|
6
|
+
validates :instance_url, presence: true
|
7
|
+
|
8
|
+
after_save :ensure_only_one_record
|
9
|
+
|
10
|
+
def self.save_from_omniauth!(auth)
|
11
|
+
where(auth.slice(:uid).permit!).first_or_initialize.tap do |user|
|
12
|
+
user.uid = auth.uid
|
13
|
+
user.name = auth.info.name
|
14
|
+
user.oauth_token = auth.credentials.token
|
15
|
+
user.refresh_token = auth.credentials.refresh_token
|
16
|
+
user.instance_url = auth.credentials.instance_url
|
17
|
+
user.save!
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def ensure_only_one_record
|
22
|
+
self.class.where{id != self.id}.destroy_all
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
<div class="salesforce-settings">
|
2
|
+
|
3
|
+
<%= page_heading(self, "Salesforce Setup") %>
|
4
|
+
|
5
|
+
<p>When Accounts makes calls to Salesforce's API, it must do so on behalf of a
|
6
|
+
specific Salesforce user. At any one time, Accounts has information for either
|
7
|
+
zero or one such user. Use the link below to set the current user that Accounts
|
8
|
+
acts as when calling the Salesforce API.</p>
|
9
|
+
|
10
|
+
<% @user = OpenStax::Salesforce::User.first %>
|
11
|
+
|
12
|
+
<div style="margin: 30px 0px">
|
13
|
+
<p>
|
14
|
+
<% if @user.present? %>
|
15
|
+
The current Salesforce user is <b><%= @user.name || "[Unknown Name]" %></b>.
|
16
|
+
<% else %>
|
17
|
+
There <b>is no</b> Salesforce user currently set.
|
18
|
+
<% end %>
|
19
|
+
</p>
|
20
|
+
</div>
|
21
|
+
|
22
|
+
<%= link_to "Set Salesforce User",
|
23
|
+
"/auth/salesforce?redirect_uri=#{main_app.auth_salesforce_callback_url}",
|
24
|
+
id: "sign_in", class: 'btn btn-primary' %>
|
25
|
+
|
26
|
+
<%= link_to "Clear Salesforce User",
|
27
|
+
destroy_user_settings_path,
|
28
|
+
class: 'btn btn-danger pull-right',
|
29
|
+
method: :delete %>
|
30
|
+
|
31
|
+
<hr/>
|
32
|
+
|
33
|
+
</div>
|
@@ -0,0 +1,8 @@
|
|
1
|
+
Rails.application.config.middleware.use OmniAuth::Builder do
|
2
|
+
unless OpenStax::Salesforce.configuration.skip_automatic_omniauth_setup
|
3
|
+
provider :salesforce,
|
4
|
+
OpenStax::Salesforce.configuration.salesforce_client_key,
|
5
|
+
OpenStax::Salesforce.configuration.salesforce_client_secret,
|
6
|
+
client_options: OpenStax::Salesforce.configuration.salesforce_client_options
|
7
|
+
end
|
8
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# This initializer always runs before the engine is loaded, but it can
|
2
|
+
# also be copied to the application's initializers by running the install
|
3
|
+
# task. Because this code can get run multiple times, make sure to only put
|
4
|
+
# code here that is amenable to that.
|
5
|
+
|
6
|
+
OpenStax::Salesforce.configure do |config|
|
7
|
+
# Layout to be used for OpenStax::Salesforce's controllers
|
8
|
+
config.layout = 'application'
|
9
|
+
|
10
|
+
# Proc called with a controller as self. Returns the current user.
|
11
|
+
config.current_user_proc = -> { nil }
|
12
|
+
|
13
|
+
# Proc called with a user as argument and a controller as self.
|
14
|
+
# This proc is called when a user tries to access the engine's controllers.
|
15
|
+
# Should raise an exception, render or redirect unless the user is a manager
|
16
|
+
# or admin. The default renders 403 Forbidden for all users.
|
17
|
+
# Note: Proc must account for nil users, if current_user_proc returns nil.
|
18
|
+
config.authenticate_admin_proc = ->(user) { head(:forbidden) }
|
19
|
+
|
20
|
+
# Consumer key and secret for connecting to the Salesforce app
|
21
|
+
config.salesforce_client_key = 'put_real_key_value_here'
|
22
|
+
config.salesforce_client_secret = 'put_real_secret_value_here'
|
23
|
+
|
24
|
+
# Uncomment this to override the login site for sandbox instances; ok to be nil
|
25
|
+
# config.salesforce_login_site = 'https://test.salesforce.com'
|
26
|
+
|
27
|
+
# The following sandbox tokens are used for specs to connect to a sandbox Salesforce
|
28
|
+
# instance.
|
29
|
+
if Rails.env.test?
|
30
|
+
config.sandbox_oauth_token = 'put_real_value_here'
|
31
|
+
config.sandbox_refresh_token = 'put_real_value_here'
|
32
|
+
config.sandbox_instance_url = 'put_real_value_here'
|
33
|
+
end
|
34
|
+
|
35
|
+
# Change this to true if you want to call the omniauth setup on your own
|
36
|
+
config.skip_automatic_omniauth_setup = false
|
37
|
+
|
38
|
+
# If `check_sandbox_instance_url` is true (default), the spec helper that
|
39
|
+
# uses the instance URL will checks that the URL starts with "cs", which
|
40
|
+
# indicates that the instance is a sandbox.
|
41
|
+
config.check_sandbox_instance_url = true
|
42
|
+
|
43
|
+
# A way to customize page headings. Sometimes apps fold the page heading
|
44
|
+
# into the layout in different ways.
|
45
|
+
config.page_heading_proc = ->(view, text) { "<h2>#{text}</h2>".html_safe }
|
46
|
+
end
|
47
|
+
|
48
|
+
|
data/config/routes.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
class InstallOpenStaxSalesforce < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :openstax_salesforce_users do |t|
|
4
|
+
t.string :name
|
5
|
+
t.string :uid, null: false
|
6
|
+
t.string :oauth_token, null: false
|
7
|
+
t.string :refresh_token, null: false
|
8
|
+
t.string :instance_url, null: false
|
9
|
+
t.timestamps
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# Monkey patching
|
2
|
+
|
3
|
+
module ActiveForce
|
4
|
+
|
5
|
+
class << self
|
6
|
+
|
7
|
+
# Use a lazy setting of the client so that migrations etc are in place
|
8
|
+
# to allow the Client to be successfully instantiated.
|
9
|
+
alias_method :original_sfdc_client, :sfdc_client
|
10
|
+
def sfdc_client
|
11
|
+
if !original_sfdc_client.is_a?(OpenStax::Salesforce::Client)
|
12
|
+
self.sfdc_client = OpenStax::Salesforce::Client.new
|
13
|
+
end
|
14
|
+
original_sfdc_client
|
15
|
+
end
|
16
|
+
|
17
|
+
def clear_sfdc_client!
|
18
|
+
self.sfdc_client = nil
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
class SObject
|
24
|
+
# Save that precious SF API call count!
|
25
|
+
def save_if_changed
|
26
|
+
save if changed?
|
27
|
+
end
|
28
|
+
|
29
|
+
# We sometimes mock `query` in specs, and it is helpful to have
|
30
|
+
# access to the original implementation
|
31
|
+
singleton_class.send(:alias_method, :original_query, :query)
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module OpenStax::Salesforce
|
2
|
+
class Client < ::Restforce::Data::Client
|
3
|
+
|
4
|
+
def initialize
|
5
|
+
user = User.first
|
6
|
+
|
7
|
+
raise(UserMissing, "The Salesforce client was requested but no user is available.") if user.nil?
|
8
|
+
|
9
|
+
client_key = OpenStax::Salesforce.configuration.salesforce_client_key
|
10
|
+
client_secret = OpenStax::Salesforce.configuration.salesforce_client_secret
|
11
|
+
|
12
|
+
raise(IllegalState, "The Salesforce key is missing") if client_key.nil?
|
13
|
+
raise(IllegalState, "The Salesforce secret is missing") if client_secret.nil?
|
14
|
+
|
15
|
+
super(oauth_token: user.oauth_token,
|
16
|
+
refresh_token: user.refresh_token,
|
17
|
+
instance_url: user.instance_url,
|
18
|
+
client_id: client_key,
|
19
|
+
client_secret: client_secret,
|
20
|
+
api_version: '37.0')
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module OpenStax::Salesforce::Remote
|
2
|
+
class Contact < ActiveForce::SObject
|
3
|
+
belongs_to :school, foreign_key: :school_id,
|
4
|
+
model: OpenStax::Salesforce::Remote::School
|
5
|
+
|
6
|
+
field :name, from: "Name"
|
7
|
+
field :first_name, from: "FirstName"
|
8
|
+
field :last_name, from: "LastName"
|
9
|
+
field :email, from: "Email"
|
10
|
+
field :email_alt, from: "Email_alt__c"
|
11
|
+
field :faculty_confirmed_date, from: "Faculty_Confirmed_Date__c", as: :datetime
|
12
|
+
field :faculty_verified, from: "Faculty_Verified__c"
|
13
|
+
field :last_modified_at, from: "LastModifiedDate"
|
14
|
+
field :school_id, from: "AccountId"
|
15
|
+
|
16
|
+
self.table_name = 'Contact'
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module OpenStax::Salesforce::Remote
|
2
|
+
class Lead < ActiveForce::SObject
|
3
|
+
field :name, from: "Name"
|
4
|
+
field :first_name, from: "FirstName"
|
5
|
+
field :last_name, from: "LastName"
|
6
|
+
field :salutation, from: "Salutation"
|
7
|
+
field :subject, from: "Subject__c"
|
8
|
+
field :school, from: "Company"
|
9
|
+
field :phone, from: "Phone"
|
10
|
+
field :website, from: "Website"
|
11
|
+
field :status, from: "Status"
|
12
|
+
field :email, from: "Email"
|
13
|
+
field :source, from: "LeadSource"
|
14
|
+
field :newsletter, from: "Newsletter__c"
|
15
|
+
field :newsletter_opt_in, from: "Newsletter_Opt_In__c"
|
16
|
+
field :adoption_status, from: "Adoption_Status__c"
|
17
|
+
field :num_students, from: "Number_of_Students__c"
|
18
|
+
field :os_accounts_id, from: "OS_Accounts_ID__c"
|
19
|
+
|
20
|
+
self.table_name = 'Lead'
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
module OpenStax::Salesforce::SpecHelpers
|
2
|
+
class SalesforceProxy
|
3
|
+
|
4
|
+
include OpenStax::Salesforce::Remote
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
end
|
8
|
+
|
9
|
+
# Used to filter records to the scope of one spec
|
10
|
+
def reset_unique_token(token = SecureRandom.hex(10))
|
11
|
+
@unique_token = token
|
12
|
+
end
|
13
|
+
|
14
|
+
def clear_unique_token
|
15
|
+
@unique_token = nil
|
16
|
+
end
|
17
|
+
|
18
|
+
def new_contact(first_name: nil, last_name: nil, school_name: "JP University",
|
19
|
+
email: nil, email_alt: nil,
|
20
|
+
faculty_verified: nil)
|
21
|
+
ensure_schools_exist([school_name])
|
22
|
+
|
23
|
+
Contact.new(
|
24
|
+
first_name: first_name || Faker::Name.first_name,
|
25
|
+
last_name: last_name!(last_name),
|
26
|
+
school_id: school_id(school_name),
|
27
|
+
email: email,
|
28
|
+
email_alt: email_alt,
|
29
|
+
faculty_verified: faculty_verified
|
30
|
+
).tap do |contact|
|
31
|
+
if !contact.save
|
32
|
+
raise "Could not save SF contact: #{contact.errors}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def new_lead(email:, status: nil, last_name: nil, school_name: "JP University")
|
38
|
+
Lead.new(
|
39
|
+
email: email,
|
40
|
+
status: status,
|
41
|
+
last_name: last_name!(last_name),
|
42
|
+
school: school_name
|
43
|
+
).tap do |lead|
|
44
|
+
if !lead.save
|
45
|
+
raise "Could not save SF lead: #{lead.errors}"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def last_name!(input)
|
51
|
+
"#{input || Faker::Name.last_name}#{@unique_token if @unique_token.present?}"
|
52
|
+
end
|
53
|
+
|
54
|
+
def ensure_books_exist(book_names)
|
55
|
+
book_names.each do |book_name|
|
56
|
+
if books.none?{|bb| bb.name == book_name}
|
57
|
+
book = Book.new(name: book_name)
|
58
|
+
book.save!
|
59
|
+
books.push(book)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def ensure_schools_exist(school_names)
|
65
|
+
school_names.compact.each do |school_name|
|
66
|
+
if schools.none?{|ss| ss.name == school_name}
|
67
|
+
school = School.new(name: school_name)
|
68
|
+
school.save!
|
69
|
+
schools.push(school)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def books
|
75
|
+
@books ||= Book.all
|
76
|
+
end
|
77
|
+
|
78
|
+
def book(name)
|
79
|
+
books.select{|bb| bb.name == name}.first
|
80
|
+
end
|
81
|
+
|
82
|
+
def book_id(name)
|
83
|
+
book(name).id
|
84
|
+
end
|
85
|
+
|
86
|
+
def schools
|
87
|
+
@schools ||= School.all
|
88
|
+
end
|
89
|
+
|
90
|
+
def school_id(name)
|
91
|
+
school(name).try(:id)
|
92
|
+
end
|
93
|
+
|
94
|
+
def school(name)
|
95
|
+
schools.select{|ss| ss.name == name}.first
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'openstax/salesforce/spec_helpers/salesforce_proxy'
|
2
|
+
|
3
|
+
module OpenStax::Salesforce::SpecHelpers
|
4
|
+
|
5
|
+
def load_salesforce_user
|
6
|
+
clear_salesforce_user
|
7
|
+
|
8
|
+
config = OpenStax::Salesforce.configuration
|
9
|
+
sf_user = OpenStax::Salesforce::User.new
|
10
|
+
|
11
|
+
sf_user.name = "some name"
|
12
|
+
sf_user.uid = "whatever"
|
13
|
+
sf_user.oauth_token = config.sandbox_oauth_token
|
14
|
+
sf_user.refresh_token = config.sandbox_refresh_token
|
15
|
+
sf_user.instance_url = config.sandbox_instance_url.tap do |url|
|
16
|
+
if config.check_sandbox_instance_url && !url.match(/\/\/cs/)
|
17
|
+
raise "Salesforce sandbox instance URL (#{url}) does not have the expected form!"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
sf_user.save!
|
22
|
+
end
|
23
|
+
|
24
|
+
def clear_salesforce_user
|
25
|
+
OpenStax::Salesforce::User.destroy_all
|
26
|
+
end
|
27
|
+
|
28
|
+
def limit_salesforce_queries(remote_class, **conditions)
|
29
|
+
allow(remote_class).to receive(:query) do
|
30
|
+
like_conditions = {}
|
31
|
+
other_conditions = {}
|
32
|
+
|
33
|
+
conditions.each_pair do |key, value|
|
34
|
+
if value.is_a?(String) && value.include?("%")
|
35
|
+
like_conditions[key] = value
|
36
|
+
else
|
37
|
+
other_conditions[key] = value
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
like_queries = like_conditions.map do |key, value|
|
42
|
+
attribute = remote_class.mapping.mappings[key]
|
43
|
+
quoted_value = "'#{value.gsub(/\\/, '\&\&').gsub(/'/, "''")}'"
|
44
|
+
"#{attribute} LIKE #{quoted_value}"
|
45
|
+
end
|
46
|
+
|
47
|
+
result = remote_class.original_query
|
48
|
+
|
49
|
+
like_queries.each do |like_query|
|
50
|
+
result = result.where(like_query)
|
51
|
+
end
|
52
|
+
|
53
|
+
result = result.where(other_conditions) if other_conditions.any?
|
54
|
+
result
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|