mycrm 0.0.41
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 +112 -0
- data/Rakefile +16 -0
- data/lib/mycrm.rb +48 -0
- data/lib/mycrm/attributes.rb +5 -0
- data/lib/mycrm/attributes/address.rb +13 -0
- data/lib/mycrm/attributes/date.rb +13 -0
- data/lib/mycrm/attributes/deposit.rb +12 -0
- data/lib/mycrm/attributes/name.rb +18 -0
- data/lib/mycrm/attributes/organization.rb +13 -0
- data/lib/mycrm/connectable.rb +107 -0
- data/lib/mycrm/core_ext.rb +7 -0
- data/lib/mycrm/core_ext/address.rb +26 -0
- data/lib/mycrm/core_ext/hash.rb +28 -0
- data/lib/mycrm/core_ext/string.rb +24 -0
- data/lib/mycrm/domains.rb +57 -0
- data/lib/mycrm/facade.rb +98 -0
- data/lib/mycrm/facades.rb +3 -0
- data/lib/mycrm/facades/lead.rb +24 -0
- data/lib/mycrm/facades/lead_application.rb +28 -0
- data/lib/mycrm/facades/organization.rb +14 -0
- data/lib/mycrm/model.rb +203 -0
- data/lib/mycrm/models.rb +9 -0
- data/lib/mycrm/models/adviser.rb +62 -0
- data/lib/mycrm/models/adviser_compliance_detail.rb +26 -0
- data/lib/mycrm/models/adviser_note.rb +23 -0
- data/lib/mycrm/models/application.rb +38 -0
- data/lib/mycrm/models/client.rb +40 -0
- data/lib/mycrm/models/lender.rb +16 -0
- data/lib/mycrm/models/note.rb +27 -0
- data/lib/mycrm/models/office.rb +48 -0
- data/lib/mycrm/models/office_address.rb +37 -0
- data/lib/mycrm/models/structure.rb +22 -0
- data/lib/mycrm/resources/domains.yml +73 -0
- data/lib/mycrm/version.rb +3 -0
- metadata +221 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c2d05640d72f98ddd72af6846858fbbd30e8acd6
|
4
|
+
data.tar.gz: fe35fee156ef2586a2badf552716e5ebff67c916
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: e2dbbe09306e7f9455ed9b4516bab95407c6a2df10adb09a3938c426a3cb62edef108d2a828b14f6d8df2ede2aa2cd35699ce3bd392b1cf6dcf3099ff4844c1c
|
7
|
+
data.tar.gz: dd87fc2be3e1d11f458abf02c6026d76b2f621ee4a95bc0239067e2bd9be1bba6cc74aa48d38ac14392e6f17a8cb46629fb37870e58eb5f2ac6f4e261fed48ff
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2017 Danilo Lo Santo
|
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,112 @@
|
|
1
|
+
# Mycrm Gem
|
2
|
+
|
3
|
+
A library to simplify communication with the MyCrm data service.
|
4
|
+
|
5
|
+
## Configuration
|
6
|
+
|
7
|
+
```
|
8
|
+
storage = Redis.new({"host"=>"localhost", "port"=>6379, "namespace"=>"loan-market-platform-development"})
|
9
|
+
Mycrm.configure do |conf|
|
10
|
+
conf.base_uri = 'https://api.endopoint.com'
|
11
|
+
conf.username = 'some-user-name'
|
12
|
+
conf.password = 'very-secret'
|
13
|
+
conf.logger = ::Logger.new(STDOUT)
|
14
|
+
conf.storage = storage
|
15
|
+
conf.token_storage_expiry = 600 # in seconds default 10 minutes (600)
|
16
|
+
# it overrides the default domains' values
|
17
|
+
conf.domains = {
|
18
|
+
sources: {
|
19
|
+
lm_contact_us: -9
|
20
|
+
},
|
21
|
+
purposes: {
|
22
|
+
first_home: 17207
|
23
|
+
},
|
24
|
+
loan_features:{
|
25
|
+
other: 16928
|
26
|
+
},
|
27
|
+
adviser_sources:{
|
28
|
+
loan_market_careers_website: 16
|
29
|
+
},
|
30
|
+
adviser_types:{
|
31
|
+
mortgage_broker: 7829
|
32
|
+
},
|
33
|
+
other_option:{
|
34
|
+
other: 36928
|
35
|
+
}
|
36
|
+
}
|
37
|
+
end
|
38
|
+
```
|
39
|
+
|
40
|
+
## Create a new simple lead
|
41
|
+
|
42
|
+
```
|
43
|
+
lead = Mycrm::Facades::Lead.new
|
44
|
+
lead.first_name = 'Michael'
|
45
|
+
lead.last_name = 'Stephens'
|
46
|
+
lead.email = 'michael.stephens@example.com'
|
47
|
+
lead.mobile = '0555123457'
|
48
|
+
lead.home_address = '135 King Street, 2000, Sydney, NSW, Australia'
|
49
|
+
lead.mobile_validated = true
|
50
|
+
lead.allocated_broker_id = 858860
|
51
|
+
lead.source = 'Lm Contact Us'
|
52
|
+
lead.activity_title = 'Gem Enquiry!'
|
53
|
+
lead.activity_details = 'I would like to ask...'
|
54
|
+
|
55
|
+
lead.create!
|
56
|
+
```
|
57
|
+
|
58
|
+
## Create a new lead with loan application
|
59
|
+
|
60
|
+
```
|
61
|
+
lead = Mycrm::Facades::LeadApplication.new
|
62
|
+
lead.first_name = 'Michael'
|
63
|
+
lead.last_name = 'Stephens'
|
64
|
+
lead.email = 'michael.stephens@example.com'
|
65
|
+
lead.mobile = '0555123457'
|
66
|
+
lead.home_address = '135 King Street, Sydney, 2000, NSW'
|
67
|
+
lead.mobile_validated = true
|
68
|
+
lead.allocated_broker_id = 858860
|
69
|
+
lead.source = 'Lm Contact Us'
|
70
|
+
lead.settlement_date = "2017-06-06T23:38:18.609Z"
|
71
|
+
lead.add_purpose 'First Home'
|
72
|
+
lead.add_feature 'Other'
|
73
|
+
lead.loan_term = 120
|
74
|
+
lead.loan_amount = 35000
|
75
|
+
lead.activity_title = 'Gem Enquiry!'
|
76
|
+
lead.activity_details = 'I would like to ask...'
|
77
|
+
|
78
|
+
lead.create!
|
79
|
+
```
|
80
|
+
|
81
|
+
## Create a new prospect adviser
|
82
|
+
```
|
83
|
+
adviser = Mycrm::Models::Adviser.new
|
84
|
+
adviser.first_name = 'James'
|
85
|
+
adviser.last_name = 'Smith'
|
86
|
+
adviser.email = 'james.smith@example.com'
|
87
|
+
adviser.mobile = '0555123457'
|
88
|
+
adviser.business_phone = '0405666555'
|
89
|
+
adviser.business_address = '135 King Street, Sydney, 2000, NSW'
|
90
|
+
adviser.summary = "I'm looking for job!"
|
91
|
+
adviser.source = 'Loan Market Careers Website'
|
92
|
+
adviser.reporting_country = 'Australia'
|
93
|
+
adviser.type = 'Mortgage Broker'
|
94
|
+
|
95
|
+
adviser.create!
|
96
|
+
```
|
97
|
+
|
98
|
+
## Development
|
99
|
+
|
100
|
+
### Running tests in development
|
101
|
+
|
102
|
+
Some of the tests run against the test instance of the actual My CRM API.
|
103
|
+
|
104
|
+
To run these locally add a `.env.local` file with `API_BASE_URI`, `API_USERNAME`, and `API_PASSWORD`:
|
105
|
+
|
106
|
+
```
|
107
|
+
API_BASE_URI=https://testapi.nzfsg.co.nz
|
108
|
+
API_USERNAME=$api-user-email
|
109
|
+
API_PASSWORD=$api-user-password
|
110
|
+
```
|
111
|
+
|
112
|
+
Get the propper details off one of the Loan Market developers.
|
data/Rakefile
ADDED
@@ -0,0 +1,16 @@
|
|
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 = 'Mycrm'
|
12
|
+
# rdoc.options << '--line-numbers'
|
13
|
+
# rdoc.rdoc_files.include('lib/**/*.rb')
|
14
|
+
# end
|
15
|
+
|
16
|
+
Bundler::GemHelper.install_tasks
|
data/lib/mycrm.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'mycrm/core_ext'
|
3
|
+
|
4
|
+
require 'mycrm/attributes'
|
5
|
+
require 'mycrm/connectable'
|
6
|
+
require 'mycrm/domains'
|
7
|
+
require 'mycrm/facades'
|
8
|
+
require 'mycrm/models'
|
9
|
+
require 'mycrm/version'
|
10
|
+
|
11
|
+
module Mycrm
|
12
|
+
class << self
|
13
|
+
attr_reader :configuration
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
attr_writer :configuration
|
18
|
+
|
19
|
+
def set_domains
|
20
|
+
configuration.domains = YAML.load_file(domains_file)
|
21
|
+
.depp_merge(configuration.domains.to_h.stringify_keys_deep!)
|
22
|
+
.stringify_keys_deep!
|
23
|
+
end
|
24
|
+
|
25
|
+
def domains_file
|
26
|
+
File.join(File.dirname(__FILE__), 'mycrm/resources', 'domains.yml')
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.configure
|
31
|
+
self.configuration = Configuration.new
|
32
|
+
yield(configuration)
|
33
|
+
set_domains
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.log(level, message)
|
37
|
+
return unless configuration.logger
|
38
|
+
configuration.logger.send level, message
|
39
|
+
end
|
40
|
+
|
41
|
+
class Configuration
|
42
|
+
attr_accessor :base_uri, :username, :password, :logger, :domains, :storage, :token_storage_expiry
|
43
|
+
end
|
44
|
+
|
45
|
+
class ApiError < StandardError; end
|
46
|
+
class ResponseError < StandardError; end
|
47
|
+
class ConnectionError < StandardError; end
|
48
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'virtus'
|
2
|
+
|
3
|
+
module Mycrm
|
4
|
+
module Attributes
|
5
|
+
class Name
|
6
|
+
include Virtus.model
|
7
|
+
|
8
|
+
attribute :display, String #, default: :default_display_name
|
9
|
+
attribute :first, String
|
10
|
+
attribute :last, String
|
11
|
+
attribute :middle, String
|
12
|
+
|
13
|
+
def set_default_display_name
|
14
|
+
self.display = [first, last].join(' ') if first || last
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module Mycrm
|
5
|
+
# this module adds connectivity methods to the descendant's class
|
6
|
+
module Connectable
|
7
|
+
TOKEN_KEY = 'mycrm_auth_token_key'
|
8
|
+
DEFAULT_TOKEN_EXPIRE_IN_STORAGE = 600 # 10 minutes
|
9
|
+
|
10
|
+
def self.extended(descendant)
|
11
|
+
descendant.send(:extend, ExtendedMethods)
|
12
|
+
end
|
13
|
+
|
14
|
+
class << self
|
15
|
+
#create the connection with basic configurations
|
16
|
+
def connection
|
17
|
+
Faraday.new(url: Mycrm.configuration.base_uri) do |faraday|
|
18
|
+
faraday.request :url_encoded
|
19
|
+
if Mycrm.configuration.logger
|
20
|
+
faraday.response :logger, Mycrm.configuration.logger, bodies: true
|
21
|
+
end
|
22
|
+
yield(faraday) if block_given?
|
23
|
+
faraday.adapter Faraday.default_adapter
|
24
|
+
end
|
25
|
+
rescue Errno::ECONNREFUSED => e
|
26
|
+
raise ConnectionError, e
|
27
|
+
end
|
28
|
+
|
29
|
+
def token
|
30
|
+
@token || fetch_token
|
31
|
+
end
|
32
|
+
|
33
|
+
def fetch_token
|
34
|
+
storage = Mycrm.configuration.storage # Redis or any strategy that implement set and get
|
35
|
+
|
36
|
+
if storage
|
37
|
+
token = storage.get(TOKEN_KEY)
|
38
|
+
if token && !(token.nil? || token.empty?)
|
39
|
+
token
|
40
|
+
else
|
41
|
+
token_storage_expiry = Mycrm.configuration.token_storage_expiry || DEFAULT_TOKEN_EXPIRE_IN_STORAGE
|
42
|
+
token = fetch_token_from_mycrm
|
43
|
+
storage.set(TOKEN_KEY, token, ex: token_storage_expiry)
|
44
|
+
token
|
45
|
+
end
|
46
|
+
else
|
47
|
+
fetch_token_from_mycrm
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def fetch_token_from_mycrm
|
52
|
+
connection.post('/Login', credentials).body
|
53
|
+
end
|
54
|
+
|
55
|
+
def credentials
|
56
|
+
%w(username password).each_with_object({}) do |f, o|
|
57
|
+
o[f] = Mycrm.configuration.send(f)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def session
|
62
|
+
@token = token
|
63
|
+
yield if block_given?
|
64
|
+
ensure
|
65
|
+
@token = nil
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# private module to be extended
|
70
|
+
module ExtendedMethods
|
71
|
+
|
72
|
+
def connection
|
73
|
+
Mycrm::Connectable.connection do |faraday|
|
74
|
+
faraday.headers['Authorization'] = "Bearer #{skim(Mycrm::Connectable.token)}"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def respond(response)
|
79
|
+
raise ResponseError, skim(response.body) unless response.success?
|
80
|
+
raise ResponseError, 'Not found' if 'null'.eql?(skim(response.body))
|
81
|
+
parse(response.body)
|
82
|
+
end
|
83
|
+
|
84
|
+
def parse(body)
|
85
|
+
JSON.parse(body)
|
86
|
+
rescue JSON::ParserError
|
87
|
+
raise ResponseError, "#{skim(body)} is not in a valid format"
|
88
|
+
end
|
89
|
+
|
90
|
+
def skim(string)
|
91
|
+
string.to_s.gsub(/\A"|"\Z/, '')
|
92
|
+
end
|
93
|
+
|
94
|
+
%w(get post put delete).each do |method|
|
95
|
+
define_method method do |uri, body = {}, query = {}|
|
96
|
+
response = connection.send(method, uri, query) do |req|
|
97
|
+
req.headers['Content-Type'] = 'application/json'
|
98
|
+
req.body = JSON.generate(body)
|
99
|
+
req.options.timeout = 120
|
100
|
+
req.options.open_timeout = 20
|
101
|
+
end
|
102
|
+
respond(response)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Mycrm
|
2
|
+
module CoreExt
|
3
|
+
class Address
|
4
|
+
FIELDS = [:formatted, :street, :suburb, :state, :postcode, :country]
|
5
|
+
|
6
|
+
attr_reader *FIELDS
|
7
|
+
|
8
|
+
alias to_s formatted
|
9
|
+
|
10
|
+
def initialize(formatted, locale = :en_au)
|
11
|
+
@formatted = formatted
|
12
|
+
expand(locale)
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_h
|
16
|
+
FIELDS.reject{ |f| f == :formatted }.each_with_object({}){ |f, out| out[f] = send(f) }
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def expand(locale)
|
22
|
+
@street, @suburb, @state, @postcode, @country = *formatted.split(',').map(&:strip)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Mycrm
|
2
|
+
module CoreExt
|
3
|
+
module Hash
|
4
|
+
def symbolize_keys_deep!
|
5
|
+
self.replace modify_keys_deep(:to_sym)
|
6
|
+
end
|
7
|
+
|
8
|
+
def stringify_keys_deep!
|
9
|
+
self.replace modify_keys_deep(:to_s)
|
10
|
+
end
|
11
|
+
|
12
|
+
def modify_keys_deep(method = :to_sym )
|
13
|
+
self.each_with_object({}) do |(key, value), copy|
|
14
|
+
copy[key.send(method)] = value.kind_of?(Hash) ? value.modify_keys_deep(method) : value
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def depp_merge(newhash)
|
19
|
+
return self.dup unless newhash
|
20
|
+
# merger = -> (key, oldval, newval) { oldval.is_a? Hash ? oldval.recursive_merge(newval) : newval } # not working :(
|
21
|
+
new_hash = (newhash.keys - keys).each_with_object({}) { |k, nh| nh[k] = newhash[k] }
|
22
|
+
self.each_with_object(new_hash) do |(key, value), nh|
|
23
|
+
nh[key] = value.kind_of?(Hash) ? value.depp_merge(newhash[key]) : (newhash[key] || value)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|