fakecrm 0.9.9.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/.gitmodules +3 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +76 -0
- data/Rakefile +113 -0
- data/bin/fakecrm +37 -0
- data/fakecrm.gemspec +34 -0
- data/lib/fakecrm/application.rb +85 -0
- data/lib/fakecrm/configuration.rb +8 -0
- data/lib/fakecrm/drop.rb +59 -0
- data/lib/fakecrm/embedded.rb +32 -0
- data/lib/fakecrm/fetch.rb +139 -0
- data/lib/fakecrm/initialize.rb +16 -0
- data/lib/fakecrm/localized_dm.rb +12 -0
- data/lib/fakecrm/resource/account.rb +33 -0
- data/lib/fakecrm/resource/activity.rb +57 -0
- data/lib/fakecrm/resource/contact.rb +51 -0
- data/lib/fakecrm/resource/custom_attribute.rb +20 -0
- data/lib/fakecrm/resource/custom_type.rb +96 -0
- data/lib/fakecrm/resource/event.rb +52 -0
- data/lib/fakecrm/resource/event_contact.rb +21 -0
- data/lib/fakecrm/resource/extensions/kinds.rb +26 -0
- data/lib/fakecrm/resource/extensions/type_extender.rb +42 -0
- data/lib/fakecrm/resource/extensions/type_extension.rb +55 -0
- data/lib/fakecrm/resource/mailing.rb +30 -0
- data/lib/fakecrm/resource/password.rb +17 -0
- data/lib/fakecrm/resource/role.rb +18 -0
- data/lib/fakecrm/resource/template.rb +41 -0
- data/lib/fakecrm/resource/views/resource_view.rb +90 -0
- data/lib/fakecrm/resources.rb +11 -0
- data/lib/fakecrm/server/accounts.rb +39 -0
- data/lib/fakecrm/server/activities.rb +39 -0
- data/lib/fakecrm/server/contacts.rb +118 -0
- data/lib/fakecrm/server/custom_types.rb +34 -0
- data/lib/fakecrm/server/event_contacts.rb +38 -0
- data/lib/fakecrm/server/events.rb +47 -0
- data/lib/fakecrm/server/mailings.rb +44 -0
- data/lib/fakecrm/server/roles.rb +44 -0
- data/lib/fakecrm/server/templates.rb +24 -0
- data/lib/fakecrm/server.rb +37 -0
- data/lib/fakecrm/version.rb +5 -0
- data/lib/fakecrm.rb +36 -0
- data/locales/de.yml +25 -0
- data/locales/en.yml +25 -0
- data/test/embedded/.gitignore +15 -0
- data/test/embedded/Gemfile +6 -0
- data/test/embedded/Rakefile +7 -0
- data/test/embedded/app/models/.gitkeep +0 -0
- data/test/embedded/config/application.rb +44 -0
- data/test/embedded/config/boot.rb +6 -0
- data/test/embedded/config/environment.rb +5 -0
- data/test/embedded/config/environments/development.rb +20 -0
- data/test/embedded/config/environments/test.rb +21 -0
- data/test/embedded/config/initializers/fakecrm.rb +8 -0
- data/test/embedded/config/initializers/secret_token.rb +7 -0
- data/test/embedded/config/initializers/session_store.rb +8 -0
- data/test/embedded/config/initializers/wrap_parameters.rb +14 -0
- data/test/embedded/config/locales/en.yml +5 -0
- data/test/embedded/config/routes.rb +2 -0
- data/test/embedded/config.ru +4 -0
- data/test/embedded/lib/assets/.gitkeep +0 -0
- data/test/embedded/lib/tasks/.gitkeep +0 -0
- data/test/embedded/log/.gitkeep +0 -0
- data/test/embedded/script/rails +6 -0
- metadata +301 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: e0d190fc0cf9569dd4eb62f2d843db0febd4fa52
|
4
|
+
data.tar.gz: 9ee3ecf7a990ce957dcc1f89df3e53bcc7fb69f4
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 493c700aa1763b86db61f308f44e6eb58e9a9aef17b2a89d116667213597a2028e69810f7e7eb8416d58d13c53beec83cd15d803dce05612a6cd2a2fc288f4df
|
7
|
+
data.tar.gz: 73a8fbf4a74b10cf364ed8221f1f21a9f2501ee2603c247010ddcce706c89e72bb35a0ba590ff07fa92bfa8a766b5997a2971c453de3ea79a53169ea563dd531
|
data/.gitignore
ADDED
data/.gitmodules
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Mateusz Sojka
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
# Fakecrm
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'fakecrm', :git => git@github.com:infopark/fakecrm.git
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
## Usage
|
16
|
+
|
17
|
+
You can run this gem as standalone server with:
|
18
|
+
|
19
|
+
$ fakecrm
|
20
|
+
|
21
|
+
For help on running this command execute:
|
22
|
+
|
23
|
+
$ fakecrm --help
|
24
|
+
|
25
|
+
Another approach is to embed fakecrm directly into your application. The following describes steps neccessary for a rails application.
|
26
|
+
|
27
|
+
Assuming you added fakecrm to your application's Gemfile, you need to create an initializer, for example under `config/initializers/fakecrm.rb`:
|
28
|
+
|
29
|
+
# place your Fakecrm configuration here
|
30
|
+
Fakecrm::Configuration.silent = true
|
31
|
+
|
32
|
+
Infopark::Crm.configure do |configuration|
|
33
|
+
configuration.url = "http://localhost:#{Fakecrm::Configuration.port}/crm"
|
34
|
+
configuration.login = "root"
|
35
|
+
configuration.api_key = "deadbeef"
|
36
|
+
end
|
37
|
+
|
38
|
+
require 'fakecrm/embedded'
|
39
|
+
Fakecrm.embedded! if Rails.env.development? || Rails.env.test?
|
40
|
+
|
41
|
+
For available configuration options see the output of the command:
|
42
|
+
|
43
|
+
$ fakecrm --help
|
44
|
+
|
45
|
+
## Testing
|
46
|
+
|
47
|
+
To prepare test environment execute (you must only do it once):
|
48
|
+
|
49
|
+
$ git submodule init
|
50
|
+
$ git submodule update
|
51
|
+
|
52
|
+
Execute to update test environment:
|
53
|
+
|
54
|
+
$ git submodule update
|
55
|
+
|
56
|
+
Execute this line to run all tests:
|
57
|
+
|
58
|
+
$ rake
|
59
|
+
|
60
|
+
Open `coverage/index.html` after running the suite to see a detailed report of code coverage.
|
61
|
+
|
62
|
+
You can also run only selected test using:
|
63
|
+
|
64
|
+
$ TEST=test/crm_connector/account_search_custom_field_test.rb rake
|
65
|
+
|
66
|
+
**Some bugs only become apparent after the suite has been run two consecutive times. To handle this case execute:**
|
67
|
+
|
68
|
+
$ rake TWICE=1
|
69
|
+
|
70
|
+
## Contributing
|
71
|
+
|
72
|
+
1. Fork it
|
73
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
74
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
75
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
76
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
|
3
|
+
module Fakecrm
|
4
|
+
module SimpleTests
|
5
|
+
class Coverage
|
6
|
+
def measure
|
7
|
+
require 'simplecov'
|
8
|
+
SimpleCov.command_name 'test:crm_connector'
|
9
|
+
SimpleCov.start
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class EmbeddedTest
|
14
|
+
def app_path
|
15
|
+
@app_path ||= File.expand_path('../test/embedded', __FILE__)
|
16
|
+
end
|
17
|
+
|
18
|
+
def configure
|
19
|
+
File.open(File.join(app_path, 'config/initializers/fakecrm.rb'), 'w') do |f|
|
20
|
+
f.puts <<-EOF
|
21
|
+
Infopark::Crm.configure do |configuration|
|
22
|
+
configuration.url = "http://localhost:\#{Fakecrm::Configuration.port}/crm"
|
23
|
+
configuration.login = "root"
|
24
|
+
configuration.api_key = "deadbeef"
|
25
|
+
end
|
26
|
+
|
27
|
+
require 'fakecrm/embedded'
|
28
|
+
Fakecrm.embedded! if Rails.env.development? || Rails.env.test?
|
29
|
+
EOF
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def test
|
34
|
+
Dir.chdir(app_path)
|
35
|
+
`bundle > /dev/null && bundle exec rails runner "fail '' unless Infopark::Crm::Contact.search(:params => {:login => 'root'}).first.login == 'root'"`
|
36
|
+
raise "Embedded test failed" unless $?.success?
|
37
|
+
end
|
38
|
+
|
39
|
+
def run
|
40
|
+
$stdout.puts "Running embedded tests"
|
41
|
+
configure
|
42
|
+
test
|
43
|
+
$stdout.puts "Embedded tests successful"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class ConnectorTest
|
48
|
+
def crm_path
|
49
|
+
@crm_path ||= File.expand_path('../test/crm_connector', __FILE__)
|
50
|
+
end
|
51
|
+
|
52
|
+
def load_fakecrm
|
53
|
+
require File.expand_path('../lib/fakecrm', __FILE__)
|
54
|
+
require File.expand_path('../lib/fakecrm/embedded', __FILE__)
|
55
|
+
end
|
56
|
+
|
57
|
+
def configure_connector
|
58
|
+
File.open(File.join(crm_path,'test/local_config.rb'), 'w') do |f|
|
59
|
+
f.write <<-EOS
|
60
|
+
require 'helpful_configuration'
|
61
|
+
require 'json'
|
62
|
+
|
63
|
+
def either_file(*files)
|
64
|
+
found = files.detect do |file|
|
65
|
+
File.exists?(file)
|
66
|
+
end
|
67
|
+
raise "Could not find any of the files \#{files.join(', ')}" unless found
|
68
|
+
found
|
69
|
+
end
|
70
|
+
|
71
|
+
def local_config
|
72
|
+
{
|
73
|
+
"login" => "root",
|
74
|
+
"api_key" => "deadbeef",
|
75
|
+
"url" => "http://localhost:#{Fakecrm::Configuration.port}/crm"
|
76
|
+
}
|
77
|
+
end
|
78
|
+
EOS
|
79
|
+
end
|
80
|
+
end
|
81
|
+
def test
|
82
|
+
Dir.chdir(crm_path)
|
83
|
+
load File.join(crm_path, 'Rakefile')
|
84
|
+
Rake::Task["test"].invoke
|
85
|
+
Rake::Task["test"].execute if ENV['TWICE']
|
86
|
+
end
|
87
|
+
|
88
|
+
def start_embedded_server
|
89
|
+
require 'fakecrm/embedded'
|
90
|
+
port, pid = Fakecrm.embedded!
|
91
|
+
Fakecrm::Configuration.port = port
|
92
|
+
end
|
93
|
+
|
94
|
+
def run
|
95
|
+
load_fakecrm
|
96
|
+
start_embedded_server
|
97
|
+
configure_connector
|
98
|
+
$stdout.puts "Running connector tests"
|
99
|
+
test
|
100
|
+
$stdout.puts "Connector tests successful"
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
desc "Tests the gem"
|
107
|
+
task :testrun do
|
108
|
+
Fakecrm::SimpleTests::Coverage.new.measure unless ENV['TEST']
|
109
|
+
Fakecrm::SimpleTests::EmbeddedTest.new.run unless ENV['TEST']
|
110
|
+
Fakecrm::SimpleTests::ConnectorTest.new.run
|
111
|
+
end
|
112
|
+
|
113
|
+
task :default => :testrun
|
data/bin/fakecrm
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'optparse'
|
4
|
+
require 'rubygems'
|
5
|
+
require 'bundler'
|
6
|
+
require 'bundler/setup'
|
7
|
+
|
8
|
+
begin
|
9
|
+
require 'fakecrm'
|
10
|
+
rescue LoadError => e
|
11
|
+
require File.expand_path('../../lib/fakecrm', __FILE__)
|
12
|
+
end
|
13
|
+
|
14
|
+
conf = Fakecrm::Configuration
|
15
|
+
OptionParser.new do |opts|
|
16
|
+
opts.banner = "Usage: fakecrm [options]"
|
17
|
+
|
18
|
+
opts.on("-s", "--silent", "Run silently (disable any output)") do |s|
|
19
|
+
conf.silent = true
|
20
|
+
end
|
21
|
+
|
22
|
+
opts.on("-l", "--log-level [LEVEL]", [:fatal, :error, :warn, :info, :debug], "Select log level (off, fatal, error, warn, info, debug, default=#{conf.log_level})") do |l|
|
23
|
+
conf.log_level = l
|
24
|
+
end
|
25
|
+
|
26
|
+
opts.on("-p", "--port [PORT]", OptionParser::DecimalNumeric, "Select port to run on (default #{conf.port})") do |p|
|
27
|
+
conf.port = p
|
28
|
+
end
|
29
|
+
|
30
|
+
opts.on("-d", "--database [DATABASE", "Setup database to use fakecrm with, for example:", "#{conf.database} (default)", "mysql://user:password@hostname/database","postgres://user:password@hostname/database") do |d|
|
31
|
+
conf.database = d
|
32
|
+
end
|
33
|
+
|
34
|
+
end.parse!
|
35
|
+
|
36
|
+
|
37
|
+
Fakecrm.run!
|
data/fakecrm.gemspec
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'fakecrm/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "fakecrm"
|
8
|
+
spec.version = Fakecrm::VERSION
|
9
|
+
spec.authors = ["Mateusz Sojka", "Tomasz Przedmojski"]
|
10
|
+
spec.email = ["mateusz.sojka@infopark.de", "tomasz.przedmojski@infopark.de"]
|
11
|
+
spec.description = %q{FakeCRM is a mock implementation for the Infopark WebCRM. It can be used for offline local development and automated testing.}
|
12
|
+
spec.summary = %q{FakeCRM is a mock implementation for the Infopark WebCRM.}
|
13
|
+
spec.homepage = "https://github.com/infopark/fakecrm"
|
14
|
+
spec.license = "LGPLv3"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "pry"
|
24
|
+
spec.add_development_dependency "byebug"
|
25
|
+
spec.add_development_dependency "simplecov"
|
26
|
+
spec.add_dependency 'dm-sqlite-adapter'
|
27
|
+
spec.add_dependency 'json'
|
28
|
+
spec.add_dependency 'sinatra'
|
29
|
+
spec.add_dependency 'rack-contrib'
|
30
|
+
spec.add_dependency 'thin'
|
31
|
+
spec.add_dependency 'i18n'
|
32
|
+
spec.add_dependency 'data_mapper'
|
33
|
+
end
|
34
|
+
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'fakecrm/configuration'
|
2
|
+
require 'fakecrm/server'
|
3
|
+
|
4
|
+
module Fakecrm
|
5
|
+
class Application
|
6
|
+
include Singleton
|
7
|
+
|
8
|
+
def configure
|
9
|
+
configure_logger
|
10
|
+
configure_dm
|
11
|
+
configure_server
|
12
|
+
end
|
13
|
+
|
14
|
+
def configure_logger
|
15
|
+
level_map = {
|
16
|
+
:info => Logger::INFO,
|
17
|
+
:debug => Logger::DEBUG,
|
18
|
+
:warn => Logger::WARN,
|
19
|
+
:error => Logger::ERROR,
|
20
|
+
:fatal => Logger::FATAL
|
21
|
+
}
|
22
|
+
|
23
|
+
if Configuration.silent
|
24
|
+
Thin::Logging.silent = true
|
25
|
+
DataMapper::Logger.new($stderr, :fatal)
|
26
|
+
self.logger = Logger.new(nil)
|
27
|
+
else
|
28
|
+
DataMapper::Logger.new($stderr, Configuration.log_level)
|
29
|
+
self.logger = Logger.new($stderr, level_map[Configuration.log_level])
|
30
|
+
end
|
31
|
+
|
32
|
+
# replace sinatra logger
|
33
|
+
Fakecrm::Server.disable :logging
|
34
|
+
Fakecrm::Server.use Rack::CommonLogger, self.logger
|
35
|
+
end
|
36
|
+
|
37
|
+
def load_and_initialize
|
38
|
+
logger.debug("Loading resources")
|
39
|
+
require 'fakecrm/resources'
|
40
|
+
logger.debug("Initializing resources")
|
41
|
+
require 'fakecrm/initialize'
|
42
|
+
end
|
43
|
+
|
44
|
+
def configure_dm
|
45
|
+
logger.debug("Configuring default database to: #{Configuration.database}")
|
46
|
+
DataMapper.setup(:default, Configuration.database)
|
47
|
+
logger.debug("Configuring localizations")
|
48
|
+
I18n.load_path += Dir[File.join(File.dirname(__FILE__), '../../locales', '*.yml').to_s]
|
49
|
+
logger.debug("Using i18n files: #{I18n.load_path.inspect}")
|
50
|
+
require 'fakecrm/localized_dm'
|
51
|
+
end
|
52
|
+
|
53
|
+
def configure_server
|
54
|
+
logger.debug("Configuring server to run on port #{Configuration.port}")
|
55
|
+
Fakecrm::Server.set :port, Configuration.port
|
56
|
+
logger.debug("Switching do production environment")
|
57
|
+
Fakecrm::Server.set :environment, :production
|
58
|
+
end
|
59
|
+
|
60
|
+
def prepare!
|
61
|
+
configure
|
62
|
+
load_and_initialize
|
63
|
+
end
|
64
|
+
|
65
|
+
def run!
|
66
|
+
prepare!
|
67
|
+
start_server
|
68
|
+
end
|
69
|
+
|
70
|
+
def start_server
|
71
|
+
Fakecrm::Server.run!
|
72
|
+
end
|
73
|
+
|
74
|
+
def logger
|
75
|
+
if !@logger
|
76
|
+
$stderr.puts("Warning: Logger has not been configured! Defaulting to nil logger")
|
77
|
+
self.logger = Logger.new(nil)
|
78
|
+
end
|
79
|
+
@logger
|
80
|
+
end
|
81
|
+
|
82
|
+
protected
|
83
|
+
attr_writer :logger
|
84
|
+
end
|
85
|
+
end
|
data/lib/fakecrm/drop.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
module Fakecrm
|
3
|
+
module Drop
|
4
|
+
def create_one(resource, data)
|
5
|
+
response = {}
|
6
|
+
resource.transaction do |t|
|
7
|
+
instance = resource.new
|
8
|
+
instance.attributes = data
|
9
|
+
|
10
|
+
if instance.save
|
11
|
+
response = instance
|
12
|
+
else
|
13
|
+
status 422
|
14
|
+
response = instance.errors.to_hash
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
response.to_json
|
19
|
+
rescue ArgumentError => e
|
20
|
+
status 422
|
21
|
+
::Fakecrm.logger.error("Unable to set unknown attribute: #{e.inspect}")
|
22
|
+
{:error => "Unknown attribute"}.to_json
|
23
|
+
end
|
24
|
+
|
25
|
+
def update_one(resource, primary_key, data)
|
26
|
+
response = {}
|
27
|
+
resource.transaction do |t|
|
28
|
+
instance = resource.get!(primary_key)
|
29
|
+
::Fakecrm.logger.debug("Updating resource with: #{data.inspect}")
|
30
|
+
instance.attributes = data
|
31
|
+
if instance.save
|
32
|
+
response = {}
|
33
|
+
else
|
34
|
+
status 422
|
35
|
+
::Fakecrm.logger.debug("Updating resouce failed: #{instance.errors.to_hash.inspect}")
|
36
|
+
response = instance.errors.to_hash
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
body response.to_json
|
41
|
+
rescue ::DataMapper::ObjectNotFoundError
|
42
|
+
status 404
|
43
|
+
rescue ArgumentError => e
|
44
|
+
status 422
|
45
|
+
::Fakecrm.logger.error("Unable to set unknown attribute: #{e.inspect}")
|
46
|
+
{:error => "Unknown attribute"}.to_json
|
47
|
+
end
|
48
|
+
|
49
|
+
def destroy_one(resource, primary_key)
|
50
|
+
resource.transaction do |t|
|
51
|
+
resource.get!(primary_key).destroy
|
52
|
+
end
|
53
|
+
body {}.to_json
|
54
|
+
rescue ::DataMapper::ObjectNotFoundError
|
55
|
+
status 404
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Fakecrm
|
2
|
+
def self.embedded!
|
3
|
+
require 'fakecrm/configuration'
|
4
|
+
|
5
|
+
port = 4000 + rand(10000)
|
6
|
+
url = "http://localhost:#{port}/crm"
|
7
|
+
|
8
|
+
if defined?(Infopark::Crm)
|
9
|
+
Infopark::Crm.configure do |configuration|
|
10
|
+
configuration.url = url
|
11
|
+
configuration.login = "root"
|
12
|
+
configuration.api_key = "deadbeef"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
pid = fork do
|
17
|
+
require 'fakecrm'
|
18
|
+
Fakecrm::Configuration.port = port
|
19
|
+
Fakecrm::Configuration.database = 'sqlite::memory:'
|
20
|
+
Fakecrm::Configuration.silent = true
|
21
|
+
self.run!
|
22
|
+
exit!
|
23
|
+
end
|
24
|
+
sleep(1)
|
25
|
+
at_exit do
|
26
|
+
Process.kill("INT", pid)
|
27
|
+
Process.wait(pid)
|
28
|
+
end
|
29
|
+
|
30
|
+
return [port, pid]
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,139 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
require 'fakecrm/resource/views/resource_view'
|
3
|
+
|
4
|
+
module Fakecrm
|
5
|
+
module Fetch
|
6
|
+
def continuation
|
7
|
+
JSON.parse(Base64.decode64(params.fetch("continuation_handle", "e30=")))
|
8
|
+
rescue => exception
|
9
|
+
{}
|
10
|
+
end
|
11
|
+
|
12
|
+
def build_continuation
|
13
|
+
Base64.urlsafe_encode64(params.merge({:offset => offset+limit, :limit => limit, :include_deleted => include_deleted?.to_s}).to_json)
|
14
|
+
end
|
15
|
+
|
16
|
+
def limit
|
17
|
+
limit = params.fetch("limit", continuation.fetch("limit", "10")).to_i
|
18
|
+
(1..1000).include?(limit) ? limit : 10
|
19
|
+
end
|
20
|
+
|
21
|
+
def offset
|
22
|
+
continuation.fetch("offset", 0).to_i
|
23
|
+
end
|
24
|
+
|
25
|
+
def include_deleted?
|
26
|
+
"true" == continuation.fetch("include_deleted", params.fetch("include_deleted", "false")).to_s
|
27
|
+
end
|
28
|
+
|
29
|
+
def consider_deleted(resource)
|
30
|
+
if include_deleted?
|
31
|
+
resource.with_deleted
|
32
|
+
else
|
33
|
+
resource
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
def search(resource, builtins=[], full_text_fields=[], sort_by = nil, sort_order = 'asc')
|
39
|
+
options = {}
|
40
|
+
builtins.each do |built_in_field|
|
41
|
+
options[built_in_field.to_sym] = params[built_in_field.to_s] if params.key?(built_in_field.to_s)
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
custom_fields = []
|
46
|
+
resource.properties.each do |property|
|
47
|
+
custom_fields << property.name if property.name =~ /^custom/
|
48
|
+
end
|
49
|
+
|
50
|
+
# custom fields
|
51
|
+
params.each do |key, value|
|
52
|
+
if key =~ /^custom_/
|
53
|
+
options[key] = value
|
54
|
+
elsif key =~ /_id$/
|
55
|
+
# cast ids to integers
|
56
|
+
options[key.to_sym] = value.to_i
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# full text
|
61
|
+
if params.key?('q')
|
62
|
+
fields = []
|
63
|
+
values = []
|
64
|
+
(full_text_fields + custom_fields).each do |full_text_field|
|
65
|
+
queries = params['q'].split(/\s/)
|
66
|
+
|
67
|
+
sub_fields = []
|
68
|
+
queries.each do |query|
|
69
|
+
sub_fields << "(#{full_text_field} LIKE ?)"
|
70
|
+
values << "%#{query}%"
|
71
|
+
end
|
72
|
+
fields << (" ( " + sub_fields.join(" OR ") + " ) ") unless sub_fields.empty?
|
73
|
+
end
|
74
|
+
if !fields.empty?
|
75
|
+
options[:conditions] = [fields.join(' OR ')] + values
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
# Reject empty options to mimic WebCRM
|
80
|
+
options = options.reject { |_, value| value.nil? || value == '' }
|
81
|
+
|
82
|
+
query = resource.all(options)
|
83
|
+
# FIXME: code duplication (fetch_many)
|
84
|
+
total_count = query.count
|
85
|
+
remaining_count = total_count - offset
|
86
|
+
|
87
|
+
query_options = { :limit => limit, :offset => offset }
|
88
|
+
|
89
|
+
if sort_by
|
90
|
+
sort_order ||= 'asc'
|
91
|
+
sort_order = 'asc' unless ['asc', 'desc'].include?(sort_order.downcase)
|
92
|
+
if sort_by.to_sym == :updated_at
|
93
|
+
order = { :order => [sort_by.to_sym.send(sort_order.to_sym), :id.send(sort_order.to_sym)] }
|
94
|
+
else
|
95
|
+
order = { :order => sort_by.to_sym.send(sort_order.to_sym) }
|
96
|
+
end
|
97
|
+
|
98
|
+
query_options.merge!(order)
|
99
|
+
end
|
100
|
+
|
101
|
+
result = {:results => query.all(query_options), :total => total_count}
|
102
|
+
|
103
|
+
if remaining_count > limit
|
104
|
+
result["continuation_handle"] = build_continuation
|
105
|
+
end
|
106
|
+
|
107
|
+
status 200
|
108
|
+
body result.to_json
|
109
|
+
end
|
110
|
+
|
111
|
+
def fetch_many(resource)
|
112
|
+
query = consider_deleted(resource)
|
113
|
+
remaining_count = query.count - offset
|
114
|
+
result = {:results => ResourceView.decorate(query.all(:limit => limit, :offset => offset)) }
|
115
|
+
|
116
|
+
if remaining_count > limit
|
117
|
+
result["continuation_handle"] = build_continuation
|
118
|
+
end
|
119
|
+
|
120
|
+
status 200
|
121
|
+
body result.to_json
|
122
|
+
end
|
123
|
+
|
124
|
+
def fetch_one(resource, primary_key)
|
125
|
+
begin
|
126
|
+
status 200
|
127
|
+
if resource.respond_to? :with_deleted
|
128
|
+
body ResourceView.decorate(resource.with_deleted.get!(primary_key)).to_json
|
129
|
+
else
|
130
|
+
body ResourceView.decorate(resource.get!(primary_key)).to_json
|
131
|
+
end
|
132
|
+
rescue ::DataMapper::ObjectNotFoundError => e
|
133
|
+
status 404
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
DataMapper.auto_upgrade!
|
3
|
+
|
4
|
+
contact = Fakecrm::Contact.first_or_create(:last_name => 'root', :login => 'root', :gender => 'N', :language => 'en', :email => 'root@root.org')
|
5
|
+
Fakecrm::Password.first_or_create(:password => 'root', :contact => contact)
|
6
|
+
|
7
|
+
|
8
|
+
Fakecrm::CustomType.first_or_create(:name => 'contact', :kind => 'Contact')
|
9
|
+
|
10
|
+
Fakecrm::CustomType.first_or_create(:name => 'account', :kind => 'Account')
|
11
|
+
|
12
|
+
Fakecrm::CustomType.all.each do |custom_type|
|
13
|
+
Fakecrm::TypeExtender.new(custom_type).extend!
|
14
|
+
end
|
15
|
+
|
16
|
+
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class DataMapper::Validations::ValidationErrors
|
2
|
+
def self.default_error_message(key, field, *values)
|
3
|
+
begin
|
4
|
+
message = I18n.t!(:"messages.#{key}")
|
5
|
+
rescue
|
6
|
+
::Fakecrm.logger.debug("Translation for message key #{key} not found (locale=#{I18n.locale})")
|
7
|
+
message = @@default_error_messages[key]
|
8
|
+
end
|
9
|
+
field = DataMapper::Inflector.humanize(field)
|
10
|
+
message % [field, *values].flatten
|
11
|
+
end
|
12
|
+
end
|