erp_tech_svcs 3.0.0

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.
Files changed (109) hide show
  1. data/GPL-3-LICENSE +674 -0
  2. data/README.rdoc +2 -0
  3. data/Rakefile +30 -0
  4. data/app/assets/javascripts/erp_tech_svcs/application.js +9 -0
  5. data/app/assets/stylesheets/erp_tech_svcs/application.css +7 -0
  6. data/app/controllers/erp_tech_svcs/session_controller.rb +19 -0
  7. data/app/controllers/erp_tech_svcs/user_controller.rb +40 -0
  8. data/app/helpers/erp_tech_svcs/application_helper.rb +4 -0
  9. data/app/mailers/user_mailer.rb +16 -0
  10. data/app/models/audit_log.rb +60 -0
  11. data/app/models/audit_log_item.rb +4 -0
  12. data/app/models/audit_log_item_type.rb +6 -0
  13. data/app/models/audit_log_type.rb +24 -0
  14. data/app/models/capability.rb +8 -0
  15. data/app/models/capability_type.rb +3 -0
  16. data/app/models/capable_model.rb +4 -0
  17. data/app/models/encryption_key.rb +9 -0
  18. data/app/models/extensions/contact_purpose.rb +3 -0
  19. data/app/models/extensions/contact_type.rb +3 -0
  20. data/app/models/extensions/note.rb +6 -0
  21. data/app/models/extensions/note_type.rb +3 -0
  22. data/app/models/extensions/party.rb +3 -0
  23. data/app/models/extensions/relationship_type.rb +3 -0
  24. data/app/models/extensions/role_type.rb +3 -0
  25. data/app/models/file_asset.rb +178 -0
  26. data/app/models/role.rb +17 -0
  27. data/app/models/secured_model.rb +13 -0
  28. data/app/models/user.rb +33 -0
  29. data/app/views/layouts/application.html.erb +14 -0
  30. data/app/views/layouts/erp_tech_svcs/application.html.erb +14 -0
  31. data/app/views/user_mailer/activation_needed_email.html.erb +14 -0
  32. data/app/views/user_mailer/reset_password_email.html.erb +14 -0
  33. data/config/initializers/erp_tech_svcs.rb +7 -0
  34. data/config/initializers/file_support.rb +1 -0
  35. data/config/initializers/pdfkit.rb +18 -0
  36. data/config/initializers/sorcery.rb +199 -0
  37. data/config/routes.rb +9 -0
  38. data/db/data_migrations/20110802200222_schedule_delete_expired_sessions_job.rb +15 -0
  39. data/db/data_migrations/20111111144706_setup_audit_log_types.rb +21 -0
  40. data/db/migrate/20080805000010_base_tech_services.rb +247 -0
  41. data/db/migrate/20111109161549_add_capabilites.rb +56 -0
  42. data/db/migrate/upgrade/20111109161550_update_roles.rb +33 -0
  43. data/db/migrate/upgrade/20111109161551_update_user.rb +88 -0
  44. data/lib/erp_tech_svcs/application_installer.rb +102 -0
  45. data/lib/erp_tech_svcs/config.rb +27 -0
  46. data/lib/erp_tech_svcs/engine.rb +14 -0
  47. data/lib/erp_tech_svcs/extensions/active_record/acts_as_versioned.rb +494 -0
  48. data/lib/erp_tech_svcs/extensions/active_record/has_capabilities.rb +139 -0
  49. data/lib/erp_tech_svcs/extensions/active_record/has_file_assets.rb +40 -0
  50. data/lib/erp_tech_svcs/extensions/active_record/has_roles.rb +126 -0
  51. data/lib/erp_tech_svcs/extensions.rb +5 -0
  52. data/lib/erp_tech_svcs/file_support/aws_s3_patch.rb +3 -0
  53. data/lib/erp_tech_svcs/file_support/base.rb +30 -0
  54. data/lib/erp_tech_svcs/file_support/file_manipulator.rb +37 -0
  55. data/lib/erp_tech_svcs/file_support/file_system_manager.rb +167 -0
  56. data/lib/erp_tech_svcs/file_support/manager.rb +147 -0
  57. data/lib/erp_tech_svcs/file_support/paperclip_patch.rb +28 -0
  58. data/lib/erp_tech_svcs/file_support/railties/s3_resolver.rb +79 -0
  59. data/lib/erp_tech_svcs/file_support/s3_manager.rb +211 -0
  60. data/lib/erp_tech_svcs/file_support.rb +10 -0
  61. data/lib/erp_tech_svcs/sessions/delete_expired_sessions_job.rb +40 -0
  62. data/lib/erp_tech_svcs/sessions/delete_expired_sessions_service.rb +15 -0
  63. data/lib/erp_tech_svcs/utils/attachment_fu_patch.rb +15 -0
  64. data/lib/erp_tech_svcs/utils/compass_access_negotiator.rb +57 -0
  65. data/lib/erp_tech_svcs/utils/compass_logger.rb +94 -0
  66. data/lib/erp_tech_svcs/utils/compass_pdf.rb +72 -0
  67. data/lib/erp_tech_svcs/utils/default_nested_set_methods.rb +33 -0
  68. data/lib/erp_tech_svcs/utils/pdf_processor.rb +106 -0
  69. data/lib/erp_tech_svcs/version.rb +3 -0
  70. data/lib/erp_tech_svcs.rb +20 -0
  71. data/lib/tasks/erp_tech_svcs_tasks.rake +42 -0
  72. data/spec/dummy/Rakefile +7 -0
  73. data/spec/dummy/app/assets/javascripts/application.js +9 -0
  74. data/spec/dummy/app/assets/stylesheets/application.css +7 -0
  75. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  76. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  77. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  78. data/spec/dummy/config/application.rb +43 -0
  79. data/spec/dummy/config/boot.rb +10 -0
  80. data/spec/dummy/config/database.yml +8 -0
  81. data/spec/dummy/config/environment.rb +5 -0
  82. data/spec/dummy/config/environments/spec.rb +27 -0
  83. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  84. data/spec/dummy/config/initializers/inflections.rb +10 -0
  85. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  86. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  87. data/spec/dummy/config/initializers/session_store.rb +8 -0
  88. data/spec/dummy/config/initializers/wrap_parameters.rb +12 -0
  89. data/spec/dummy/config/locales/en.yml +5 -0
  90. data/spec/dummy/config/routes.rb +3 -0
  91. data/spec/dummy/config.ru +4 -0
  92. data/spec/dummy/db/schema.rb +571 -0
  93. data/spec/dummy/db/spec.sqlite3 +0 -0
  94. data/spec/dummy/log/spec.log +2862 -0
  95. data/spec/dummy/public/404.html +26 -0
  96. data/spec/dummy/public/422.html +26 -0
  97. data/spec/dummy/public/500.html +26 -0
  98. data/spec/dummy/public/favicon.ico +0 -0
  99. data/spec/dummy/script/rails +6 -0
  100. data/spec/factories/capability_type.rb +5 -0
  101. data/spec/factories/role.rb +5 -0
  102. data/spec/factories/users.rb +9 -0
  103. data/spec/lib/erp_tech_svcs/extensions/active_record/has_roles_spec.rb +68 -0
  104. data/spec/models/audit_log_spec.rb +48 -0
  105. data/spec/models/audit_log_type_spec.rb +9 -0
  106. data/spec/models/role_spec.rb +17 -0
  107. data/spec/models/user_spec.rb +27 -0
  108. data/spec/spec_helper.rb +61 -0
  109. metadata +273 -0
@@ -0,0 +1,28 @@
1
+ module Paperclip
2
+ module Storage
3
+ module S3
4
+ def flush_writes #:nodoc:
5
+ @queued_for_write.each do |style, file|
6
+ begin
7
+ log("saving #{path(style)}")
8
+ AWS::S3::S3Object.store(path(style),
9
+ file,
10
+ bucket_name,
11
+ {:content_type => content_type,
12
+ :access => (@s3_permissions[style] || @s3_permissions[:default]),
13
+ }.merge(@s3_headers))
14
+ rescue AWS::S3::NoSuchBucket => e
15
+ create_bucket
16
+ retry
17
+ rescue AWS::S3::ResponseError => e
18
+ raise
19
+ end
20
+ end
21
+
22
+ after_flush_writes # allows attachment to clean up temp files
23
+
24
+ @queued_for_write = {}
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,79 @@
1
+ module ActionView
2
+ class S3Resolver < PathResolver
3
+ def initialize(path, pattern=nil)
4
+ raise ArgumentError, "path already is a Resolver class" if path.is_a?(Resolver)
5
+ super(pattern)
6
+ @path = path
7
+ end
8
+
9
+ def to_s
10
+ @path.to_s
11
+ end
12
+ alias :to_path :to_s
13
+
14
+ def eql?(resolver)
15
+ self.class.equal?(resolver.class) && to_path == resolver.to_path
16
+ end
17
+ alias :== :eql?
18
+
19
+ def cached(key, path_info, details, locals) #:nodoc:
20
+ file_support = ErpTechSvcs::FileSupport::Base.new(:storage => :s3)
21
+ name, prefix, partial = path_info
22
+ locals = sort_locals(locals)
23
+
24
+ if key && caching?
25
+ if @cached[key][name][prefix][partial][locals].nil? or @cached[key][name][prefix][partial][locals].empty?
26
+ @cached[key][name][prefix][partial][locals] = decorate(yield, path_info, details, locals)
27
+ else
28
+ @cached[key][name][prefix][partial][locals].each do |template|
29
+ last_update = mtime(template.identifier, file_support)
30
+ if last_update > template.updated_at
31
+ @cached[key][name][prefix][partial][locals].delete_if{|item| item.identifier == template.identifier}
32
+ @cached[key][name][prefix][partial][locals] << build_template(template.identifier, template.virtual_path, (details[:formats] || [:html] if template.formats.empty?), file_support, template.locals)
33
+ end
34
+ end
35
+ @cached[key][name][prefix][partial][locals]
36
+ end
37
+ else
38
+ fresh = decorate(yield, path_info, details, locals)
39
+ return fresh unless key
40
+
41
+ scope = @cached[key][name][prefix][partial]
42
+ cache = scope[locals]
43
+ mtime = cache && cache.map(&:updated_at).max
44
+
45
+ if !mtime || fresh.empty? || fresh.any? { |t| t.updated_at > mtime }
46
+ scope[locals] = fresh
47
+ else
48
+ cache
49
+ end
50
+ end
51
+ end
52
+
53
+ def query(path, details, formats)
54
+ file_support = ErpTechSvcs::FileSupport::Base.new(:storage => :s3)
55
+ templates = []
56
+ get_dir_entries(path, file_support).each{|p|templates << build_template(p, path.virtual, formats, file_support)}
57
+ templates
58
+ end
59
+
60
+ def get_dir_entries(path, file_support)
61
+ full_path = File.join(@path, path)
62
+ node = file_support.find_node(File.dirname(full_path))
63
+ node.nil? ? [] : node[:children].select{|child| child[:leaf]}.collect{|child| child[:id]}.select{|p|!p.scan(full_path).empty?}
64
+ end
65
+
66
+ def mtime(p, file_support)
67
+ node = file_support.find_node(p)
68
+ node[:last_modified]
69
+ end
70
+
71
+ protected
72
+
73
+ def build_template(p, virtual_path, formats, file_support, locals=nil)
74
+ handler, format = extract_handler_and_format(p, formats)
75
+ contents, message = file_support.get_contents(p)
76
+ Template.new(contents, p, handler, :virtual_path => virtual_path, :format => format, :updated_at => mtime(p, file_support), :locals => locals)
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,211 @@
1
+ require 'yaml'
2
+ require 'aws/s3'
3
+
4
+ module ErpTechSvcs
5
+ module FileSupport
6
+ class S3Manager < Manager
7
+ class << self
8
+ cattr_accessor :node_tree
9
+
10
+ def setup_connection
11
+ @@configuration = YAML::load_file(File.join(Rails.root,'config','s3.yml'))[Rails.env]
12
+
13
+ AWS::S3::Base.establish_connection!(
14
+ :access_key_id => @@configuration['access_key_id'],
15
+ :secret_access_key => @@configuration['secret_access_key']
16
+ )
17
+
18
+ @@s3_bucket = AWS::S3::Bucket.find(@@configuration['bucket'])
19
+ @@node_tree = build_node_tree
20
+ end
21
+
22
+ def reload
23
+ AWS::S3::Base.connected? ? (@@node_tree = build_node_tree(true)) : setup_connection
24
+ end
25
+
26
+ def build_node_tree(reload=false)
27
+ tree_data = [{:text => @@s3_bucket.name, :leaf => false, :id => '', :children => []}]
28
+ objects = reload ? @@s3_bucket.objects(:reload) : @@s3_bucket.objects()
29
+
30
+
31
+ nesting_depth = objects.collect{|object| object.key.split('/').count}.max
32
+ unless nesting_depth.nil?
33
+ levels = []
34
+ (1..nesting_depth).each do |i|
35
+ current_items = []
36
+ objects_this_depth = objects.collect{|object|
37
+ text = object.key.split('/')[i - 1]
38
+ path ='/' + (object.key.split('/')[0..(i-1)].join('/'))
39
+ if object.key.split('/').count >= i && current_items.select{|item| item[:text] == text and item[:path] == path}.empty?
40
+ item_hash = {:text => text, :path => path, :last_modified => object.last_modified}
41
+ current_items << item_hash
42
+ item_hash
43
+ end
44
+ }
45
+ objects_this_depth.delete_if{|item| (item.nil? or item[:text].nil?)}
46
+ levels << objects_this_depth
47
+ end
48
+
49
+ old_parents = []
50
+ new_parents = [tree_data[0]]
51
+ levels.each do |level|
52
+ old_parents = new_parents
53
+ new_parents = []
54
+ level.each do |item|
55
+ parent = old_parents.count == 1 ? old_parents.first : self.find_parent(item, old_parents)
56
+ path = File.join(parent[:id], item[:text])
57
+ child_hash = {:last_modified => item[:last_modified], :text => item[:text], :downloadPath => path, :leaf => !File.extname(item[:text]).blank?, :id => path, :children => []}
58
+ new_parents << child_hash
59
+ parent[:children] << child_hash
60
+ end
61
+ end
62
+ end
63
+
64
+ tree_data
65
+ end
66
+ end
67
+
68
+ def buckets
69
+ AWS::S3::Service.buckets
70
+ end
71
+
72
+ def bucket=(name)
73
+ @@s3_bucket = AWS::S3::Bucket.find(name)
74
+ end
75
+
76
+ def bucket
77
+ @@s3_bucket
78
+ end
79
+
80
+ def root
81
+ ''
82
+ end
83
+
84
+ def update_file(path, content)
85
+ AWS::S3::S3Object.store(path, content, bucket.name, :access => :public_read)
86
+ end
87
+
88
+ def create_file(path, name, contents)
89
+ AWS::S3::S3Object.store(File.join(path,name), contents, @@s3_bucket.name, :access => :public_read)
90
+ end
91
+
92
+ def create_folder(path, name)
93
+ AWS::S3::S3Object.store(File.join(path,name) + "/", '', @@s3_bucket.name, :access => :public_read)
94
+ end
95
+
96
+ def save_move(path, new_parent_path)
97
+ result = nil
98
+ unless self.exists? path
99
+ message = 'File does not exists'
100
+ else
101
+ name = File.basename(path)
102
+ if AWS::S3::S3Object.rename path, File.join(new_parent_path,name), @@s3_bucket.name, :copy_acl => true
103
+ message = "#{name} was moved to #{new_parent_path} successfully"
104
+ result = true
105
+ else
106
+ message = "#Error renaming {old_name}"
107
+ end
108
+ end
109
+
110
+ return result, message
111
+ end
112
+
113
+ def rename_file(path, name)
114
+ result = nil
115
+ old_name = File.basename(path)
116
+ path_pieces = path.split('/')
117
+ path_pieces.delete(path_pieces.last)
118
+ path_pieces.push(name)
119
+ new_path = path_pieces.join('/')
120
+ if AWS::S3::S3Object.rename path, new_path, @@s3_bucket.name, :copy_acl => true
121
+ message = "#{old_name} was renamed to #{name} successfully"
122
+ result = true
123
+ else
124
+ message = "#Error renaming {old_name}"
125
+ end
126
+
127
+ return result, message
128
+ end
129
+
130
+ def delete_file(path, options={})
131
+ result = nil
132
+ message = nil
133
+
134
+ node = find_node(path)
135
+
136
+ if node[:children].empty?
137
+ is_directory = !node[:leaf]
138
+ path << '/' unless node[:leaf]
139
+ result = AWS::S3::S3Object.delete path, @@s3_bucket.name, :force => true
140
+ message = "File was deleted successfully"
141
+ result = true
142
+ elsif options[:force]
143
+ node[:children].each do |child|
144
+ delete_file(child[:id], options)
145
+ end
146
+ else
147
+ message = "Folder is not empty"
148
+ end unless node.nil?
149
+
150
+ return result, message, is_directory
151
+ end
152
+
153
+ def exists?(path)
154
+ begin
155
+ path = path[1..path.length] if path.first == '/'
156
+ !AWS::S3::S3Object.find(path, @@s3_bucket.name).nil?
157
+ rescue AWS::S3::NoSuchKey
158
+ return false
159
+ end
160
+ end
161
+
162
+ def get_contents(path)
163
+ contents = nil
164
+ message = nil
165
+
166
+ path = path[1..path.length]
167
+ begin
168
+ object = AWS::S3::S3Object.find path, @@s3_bucket.name
169
+ rescue AWS::S3::NoSuchKey => error
170
+ message = 'File does not exists'
171
+ end
172
+
173
+ contents = object.value.to_s if message.nil?
174
+
175
+ return contents, message
176
+ end
177
+
178
+ def build_tree(starting_path, options={})
179
+ ErpTechSvcs::FileSupport::S3Manager.reload
180
+ node_tree = find_node(starting_path, options)
181
+ node_tree.nil? ? [] : node_tree
182
+ end
183
+
184
+ def find_node(path, options={})
185
+ parent = if options[:file_asset_holder]
186
+ super
187
+ else
188
+ parent = @@node_tree.first
189
+ unless path.nil?
190
+ path_pieces = path.split('/')
191
+ path_pieces.each do |path_piece|
192
+ next if path_piece.blank?
193
+ parent[:children].each do |child_node|
194
+ if child_node[:text] == path_piece
195
+ parent = child_node
196
+ break
197
+ end
198
+ end
199
+ end
200
+ parent = nil if parent[:id] != path
201
+ end
202
+
203
+ parent
204
+ end
205
+
206
+ parent
207
+ end
208
+
209
+ end#S3Manager
210
+ end#FileSupport
211
+ end#ErpTechSvcs
@@ -0,0 +1,10 @@
1
+ require 'erp_tech_svcs/file_support/base'
2
+ require 'erp_tech_svcs/file_support/manager'
3
+ require 'erp_tech_svcs/file_support/file_system_manager'
4
+ require 'erp_tech_svcs/file_support/s3_manager'
5
+ require 'erp_tech_svcs/file_support/aws_s3_patch'
6
+ require 'erp_tech_svcs/file_support/paperclip_patch'
7
+ require 'erp_tech_svcs/file_support/file_manipulator'
8
+
9
+ #path resolvers
10
+ require 'erp_tech_svcs/file_support/railties/s3_resolver'
@@ -0,0 +1,40 @@
1
+ module ErpTechSvcs
2
+ module Sessions
3
+ # Delayed Job to Reset Daily Assignments to Forecast
4
+ class DeleteExpiredSessionsJob
5
+
6
+ def initialize
7
+ @priority = 1
8
+ end
9
+
10
+ def perform
11
+ begin
12
+ process_job
13
+ rescue => exception
14
+ ErpTechSvcs::Util::CompassLogger.delete_expired_sessions_job.error("An unrecoverable error has occured, the job will be rescheduled: #{exception.message} : #{exception.backtrace}")
15
+ end
16
+
17
+ # Run once per day
18
+ date = Date.tomorrow
19
+ start_time = DateTime.civil(date.year, date.month, date.day, 2, 0, 1, -(5.0/24.0))
20
+
21
+ Delayed::Job.enqueue(DeleteExpiredSessionsJob.new(), @priority, start_time)
22
+ end
23
+
24
+ def self.schedule_job(schedule_dt)
25
+ Delayed::Job.enqueue(DeleteExpiredSessionsJob.new(), @priority, schedule_dt)
26
+ end
27
+
28
+ def process_job
29
+ start_time = Time.now
30
+
31
+ ErpTechSvcs::Sessions::DeleteExpiredSessionsService.new.execute
32
+
33
+ end_time = Time.now
34
+
35
+ return end_time - start_time
36
+ end
37
+
38
+ end #Close DeleteExpiredSessionsJob
39
+ end #Close Sessions
40
+ end #Close ErpTechSvcs
@@ -0,0 +1,15 @@
1
+ module ErpTechSvcs
2
+ module Sessions
3
+ class DeleteExpiredSessionsService
4
+
5
+ def initialize
6
+ @session_age = 12.hours
7
+ end
8
+
9
+ def execute
10
+ ActiveRecord::SessionStore::Session.delete_all ['updated_at < ?', @session_age.ago]
11
+ end
12
+
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ #This patch is to make the attachment_fu plugin work on Windows
2
+ #It is not necessary for 'nix operating systems, though it is not known
3
+ #to cause problems
4
+ require 'tempfile'
5
+ class Tempfile
6
+ def size
7
+ if @tmpfile
8
+ @tmpfile.fsync # added this line
9
+ @tmpfile.flush
10
+ @tmpfile.stat.size
11
+ else
12
+ 0
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,57 @@
1
+ module ErpTechSvcs
2
+ module Utils
3
+ module CompassAccessNegotiator
4
+
5
+ def has_capability?(model, capability_type, resource)
6
+ model.user_has_capability?(capability_type.to_s, resource, self)
7
+ end
8
+
9
+ def with_capability(model, capability_type, resource, &block)
10
+ if model.user_has_capability?(capability_type.to_s, resource, self)
11
+ yield
12
+ else
13
+ raise ErpTechSvcs::Utils::CompassAccessNegotiator::Errors::UserDoesNotHaveCapability
14
+ end
15
+ end
16
+
17
+ def has_access_to_widget?(widget)
18
+ widget.has_access?(self)
19
+ end
20
+
21
+ def valid_widgets(application)
22
+ widgets = []
23
+ application.widgets.each do |widget|
24
+ widgets << widget if self.has_access_to_widget?(widget)
25
+ end
26
+ widgets
27
+ end
28
+
29
+ module Errors
30
+ class CapabilityDoesNotExist < StandardError
31
+ def to_s
32
+ "Capability does not exist."
33
+ end
34
+ end
35
+
36
+ class CapabilityTypeDoesNotExist < StandardError
37
+ def to_s
38
+ "Capability type not exist."
39
+ end
40
+ end
41
+
42
+ class CapabilityAlreadytExists < StandardError
43
+ def to_s
44
+ "Capability already exists."
45
+ end
46
+ end
47
+
48
+ class UserDoesNotHaveCapability < StandardError
49
+ def to_s
50
+ "User does not have capability."
51
+ end
52
+ end
53
+ end
54
+
55
+ end#CompassAccessNegotiator
56
+ end#Utils
57
+ end#ErpTechSvcs
@@ -0,0 +1,94 @@
1
+ require 'logger'
2
+ module ErpTechSvcs
3
+ module Util
4
+ class CompassLogger
5
+ include Singleton
6
+
7
+ @@writers = {}
8
+
9
+ def CompassLogger.debug(msg)
10
+ if defined?(logger)
11
+ logger.debug(msg)
12
+ else
13
+ CompassLogger.app_logger()
14
+ @@writers["app_logger"].debug(msg)
15
+ end
16
+ end
17
+
18
+ def CompassLogger.info(msg)
19
+ if defined?(logger)
20
+ logger.info(msg)
21
+ else
22
+ CompassLogger.app_logger()
23
+ @@writers["app_logger"].info(msg)
24
+ end
25
+ end
26
+
27
+ def CompassLogger.warn(msg)
28
+ if defined?(logger)
29
+ logger.warn(msg)
30
+ else
31
+ CompassLogger.app_logger()
32
+ @@writers["app_logger"].warn(msg)
33
+ end
34
+ end
35
+
36
+ def CompassLogger.error(msg)
37
+ if defined?(logger)
38
+ logger.error(msg)
39
+ else
40
+ CompassLogger.app_logger()
41
+ @@writers["app_logger"].error(msg)
42
+ end
43
+ end
44
+
45
+ def CompassLogger.fatal(msg)
46
+ if defined?(logger)
47
+ logger.fatal(msg)
48
+ else
49
+ CompassLogger.app_logger()
50
+ @@writers["app_logger"].fatal(msg)
51
+ end
52
+ end
53
+
54
+ def CompassLogger.stdout(msg)
55
+ if CompassLogger.log_level() == 0
56
+ puts msg
57
+ end
58
+ end
59
+
60
+ def CompassLogger.method_missing(method, *args, &block)
61
+ unless @@writers.has_key?(method)
62
+ logger = Logger.new(CompassLogger.log_path(method))
63
+ logger.level = CompassLogger.log_level()
64
+ @@writers[method] = logger
65
+ end
66
+ @@writers[method]
67
+ end
68
+
69
+ def CompassLogger.app_logger()
70
+ path = "#{Rails.root}/log/#{Rails.env rescue 'rake'}.log"
71
+ unless RUBY_PLATFORM =~ /(:?mswin|mingw|darwin)/
72
+ path = "/var/log/rails/#{Rails.env rescue 'rake'}.log"
73
+ end
74
+ unless @@writers.has_key?("app_logger")
75
+ logger = Logger.new(path)
76
+ logger.level = CompassLogger.log_level()
77
+ @@writers["app_logger"] = logger
78
+ end
79
+ end
80
+
81
+ def CompassLogger.log_level()
82
+ ActiveRecord::Base.logger.level rescue Logger::DEBUG
83
+ end
84
+
85
+ def CompassLogger.log_path(method)
86
+ if RUBY_PLATFORM =~ /(:?mswin|mingw|darwin)/
87
+ return "#{Rails.root}/log/#{Rails.env rescue ''}_#{method}.log"
88
+ else
89
+ return "/var/log/rails/#{Rails.env rescue ''}_#{method}.log"
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,72 @@
1
+ module CompassPDF
2
+
3
+ class PDFXLate
4
+
5
+ # pdf xlator utility
6
+ attr_accessor :pdf_util
7
+
8
+ # options to the pdf xlator
9
+ attr_accessor :util_options
10
+
11
+ # temp file that contains the html to be xlated
12
+ attr_accessor :html_filename
13
+
14
+ # output option
15
+ attr_accessor :pdf_out_option
16
+
17
+ # pdf file generated
18
+ attr_accessor :pdf_filename
19
+
20
+ # shell command/s to invoke the xlation process and return the results
21
+ attr_accessor :command
22
+
23
+ def initialize(options={})
24
+ # lets default to using prince, we're big spenders
25
+ #options = {:pdf_util => "#{PDF_COMMAND}",:util_options => '--input=html --media=screen --baseurl=http://localhost:3000', :pdf_out_option => '-o '}.merge(options)
26
+
27
+ # lets use wkhtmltopdf, we're cheap
28
+ #options = {:pdf_util => "#{PDF_COMMAND}",:util_options => '', :pdf_out_option => ""}.merge(options)
29
+ options.each{ |k,v| self.send("#{k}=".to_sym, v) }
30
+ end
31
+
32
+ def command
33
+ # TODO: send this to a background process to do the xlate
34
+ # TODO: add timeout
35
+ # Could bog down the rails process
36
+ # cmd = "#{@pdf_util} #{@util_options} #{self.html_filename} -o #{self.pdf_out} &>/dev/null;"
37
+ cmd = "#{@pdf_util} #{@util_options} #{self.html_filename} #{self.pdf_out_option} #{pdf_filename}"
38
+ # cmd << "cat #{self.pdf_filename}"
39
+ end
40
+
41
+ def html_filename=(file_name)
42
+ @fname = file_name
43
+ end
44
+
45
+ def html_filename
46
+ @fname ||= "tmp/html_output_#{Digest::MD5.hexdigest(Time.now.to_i.to_s)}.html"
47
+ end
48
+
49
+ def pdf_filename
50
+ html_filename.sub(/\.html/, '.pdf')
51
+ end
52
+
53
+ def write_html_response(body)
54
+ File.open("#{html_filename}", "w") { |f| f.puts(body) }
55
+ end
56
+
57
+ def get_pdf_generated
58
+ pdf_contents = nil
59
+ File.open("#{pdf_filename}",'rb') do |f|
60
+ pdf_contents = f.read
61
+ end
62
+ pdf_contents
63
+ end
64
+
65
+ def invoke
66
+ puts "invoking command #{self.command}"
67
+ `#{self.command}`
68
+ #TODO: cleanup temp files, etc.
69
+ end
70
+ end
71
+
72
+ end
@@ -0,0 +1,33 @@
1
+ module ErpTechSvcs
2
+ module Utils
3
+ module DefaultNestedSetMethods
4
+ def self.included(base)
5
+ base.extend(ClassMethods)
6
+ end
7
+
8
+ def to_label
9
+ "#{description}"
10
+ end
11
+
12
+ def leaf
13
+ children.size == 0
14
+ end
15
+
16
+ def to_json_with_leaf(options = {})
17
+ self.to_json_without_leaf(options.merge(:methods => :leaf))
18
+ end
19
+ alias_method_chain :to_json, :leaf
20
+
21
+ module ClassMethods
22
+ def find_roots
23
+ where("parent_id = nil")
24
+ end
25
+
26
+ def find_children(parent_id = nil)
27
+ parent_id.to_i == 0 ? self.roots : find(parent_id).children
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+