fakecrm 0.9.9.beta1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|