smartkiosk-server 0.9.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 (254) hide show
  1. data/.gitignore +32 -0
  2. data/.rspec +1 -0
  3. data/Capfile +4 -0
  4. data/Gemfile +71 -0
  5. data/Gemfile.lock +439 -0
  6. data/Guardfile +25 -0
  7. data/LICENSE +287 -0
  8. data/README.md +13 -0
  9. data/Rakefile +5 -0
  10. data/app/acquirers/cards_mkb_acquirer.rb +87 -0
  11. data/app/acquirers/cash_acquirer.rb +22 -0
  12. data/app/admin/agents.rb +108 -0
  13. data/app/admin/collections.rb +62 -0
  14. data/app/admin/commissions.rb +87 -0
  15. data/app/admin/gateways.rb +183 -0
  16. data/app/admin/limits.rb +82 -0
  17. data/app/admin/payments.rb +246 -0
  18. data/app/admin/provider_groups.rb +60 -0
  19. data/app/admin/provider_profiles.rb +11 -0
  20. data/app/admin/provider_receipt_templates.rb +82 -0
  21. data/app/admin/providers.rb +201 -0
  22. data/app/admin/rebates.rb +83 -0
  23. data/app/admin/report_results.rb +66 -0
  24. data/app/admin/report_templates.rb +209 -0
  25. data/app/admin/reports.rb +158 -0
  26. data/app/admin/revisions.rb +120 -0
  27. data/app/admin/system_receipt_templates.rb +76 -0
  28. data/app/admin/terminal_builds.rb +39 -0
  29. data/app/admin/terminal_profiles.rb +123 -0
  30. data/app/admin/terminals.rb +388 -0
  31. data/app/admin/users.rb +117 -0
  32. data/app/admin/versions.rb +131 -0
  33. data/app/admin/welcome.rb +64 -0
  34. data/app/assets/fonts/PT_Sans-Web-Bold.eot +0 -0
  35. data/app/assets/fonts/PT_Sans-Web-Bold.svg +6386 -0
  36. data/app/assets/fonts/PT_Sans-Web-Bold.ttf +0 -0
  37. data/app/assets/fonts/PT_Sans-Web-Bold.woff +0 -0
  38. data/app/assets/fonts/PT_Sans-Web-Regular.eot +0 -0
  39. data/app/assets/fonts/PT_Sans-Web-Regular.svg +5650 -0
  40. data/app/assets/fonts/PT_Sans-Web-Regular.ttf +0 -0
  41. data/app/assets/fonts/PT_Sans-Web-Regular.woff +0 -0
  42. data/app/assets/images/chosen-sprite.png +0 -0
  43. data/app/assets/javascripts/active_admin/chosen.js.erb.coffee +12 -0
  44. data/app/assets/javascripts/active_admin/qtip.js.coffee +22 -0
  45. data/app/assets/javascripts/active_admin/sortable_forms.js.coffee +14 -0
  46. data/app/assets/javascripts/active_admin.js.coffee +9 -0
  47. data/app/assets/javascripts/application.js +15 -0
  48. data/app/assets/javascripts/report_templates.js.coffee +10 -0
  49. data/app/assets/javascripts/terminals.js.coffee +12 -0
  50. data/app/assets/stylesheets/active_admin/PIE.css.scss +18 -0
  51. data/app/assets/stylesheets/active_admin/filter_numeric_range.css.scss +14 -0
  52. data/app/assets/stylesheets/active_admin/selectable_check_boxes.css.scss +12 -0
  53. data/app/assets/stylesheets/active_admin/sortable_forms.css.scss +11 -0
  54. data/app/assets/stylesheets/active_admin.css.scss +705 -0
  55. data/app/assets/stylesheets/fonts.css.scss +14 -0
  56. data/app/assets/stylesheets/provider_groups.css.scss +12 -0
  57. data/app/assets/stylesheets/provider_receipt_templates.css.scss +12 -0
  58. data/app/assets/stylesheets/terminals.css.scss +9 -0
  59. data/app/controllers/application_controller.rb +12 -0
  60. data/app/controllers/collections_controller.rb +10 -0
  61. data/app/controllers/payments_controller.rb +73 -0
  62. data/app/controllers/system_receipt_templates_controller.rb +10 -0
  63. data/app/controllers/terminal_builds_controller.rb +5 -0
  64. data/app/controllers/terminal_orders_controller.rb +25 -0
  65. data/app/controllers/terminal_pings_controller.rb +45 -0
  66. data/app/controllers/welcome_controller.rb +5 -0
  67. data/app/helpers/active_admin/report_templates_helper.rb +56 -0
  68. data/app/helpers/active_admin/views_helper.rb +20 -0
  69. data/app/helpers/application_helper.rb +2 -0
  70. data/app/mailers/.gitkeep +0 -0
  71. data/app/models/.gitkeep +0 -0
  72. data/app/models/ability.rb +30 -0
  73. data/app/models/agent.rb +24 -0
  74. data/app/models/collection.rb +65 -0
  75. data/app/models/commission.rb +77 -0
  76. data/app/models/commission_section.rb +75 -0
  77. data/app/models/gateway.rb +99 -0
  78. data/app/models/gateway_attachment.rb +9 -0
  79. data/app/models/gateway_setting.rb +7 -0
  80. data/app/models/gateway_switch.rb +7 -0
  81. data/app/models/limit.rb +77 -0
  82. data/app/models/limit_section.rb +58 -0
  83. data/app/models/payment.rb +322 -0
  84. data/app/models/provider.rb +59 -0
  85. data/app/models/provider_field.rb +7 -0
  86. data/app/models/provider_gateway.rb +47 -0
  87. data/app/models/provider_group.rb +45 -0
  88. data/app/models/provider_profile.rb +9 -0
  89. data/app/models/provider_rebate.rb +69 -0
  90. data/app/models/provider_receipt_template.rb +85 -0
  91. data/app/models/rebate.rb +84 -0
  92. data/app/models/report.rb +71 -0
  93. data/app/models/report_result.rb +11 -0
  94. data/app/models/report_template.rb +56 -0
  95. data/app/models/revision.rb +104 -0
  96. data/app/models/role.rb +48 -0
  97. data/app/models/system_receipt_template.rb +13 -0
  98. data/app/models/terminal.rb +126 -0
  99. data/app/models/terminal_build.rb +62 -0
  100. data/app/models/terminal_order.rb +42 -0
  101. data/app/models/terminal_ping.rb +120 -0
  102. data/app/models/terminal_profile.rb +51 -0
  103. data/app/models/terminal_profile_promotion.rb +18 -0
  104. data/app/models/terminal_profile_provider.rb +11 -0
  105. data/app/models/terminal_profile_provider_group.rb +19 -0
  106. data/app/models/user.rb +38 -0
  107. data/app/models/user_role.rb +45 -0
  108. data/app/reports/agents_report.rb +81 -0
  109. data/app/reports/collections_report.rb +151 -0
  110. data/app/reports/payments_report.rb +189 -0
  111. data/app/reports/terminals_report.rb +123 -0
  112. data/app/uploaders/file_uploader.rb +53 -0
  113. data/app/uploaders/icon_uploader.rb +15 -0
  114. data/app/uploaders/zip_uploader.rb +53 -0
  115. data/app/views/admin/gateways/providers.html.arb +10 -0
  116. data/app/views/admin/revisions/payments.html.arb +28 -0
  117. data/app/views/admin/terminal_profiles/_tree.html.haml +35 -0
  118. data/app/views/admin/terminal_profiles/sort.html.haml +21 -0
  119. data/app/views/admin/terminals/pings.html.arb +55 -0
  120. data/app/views/admin/terminals/upgrade_build.html.arb +30 -0
  121. data/app/views/layouts/application.html.erb +1 -0
  122. data/app/views/welcome/index.html.erb +25 -0
  123. data/app/workers/pay_worker.rb +11 -0
  124. data/app/workers/report_worker.rb +7 -0
  125. data/app/workers/revise_worker.rb +7 -0
  126. data/config/acquiring.yml +13 -0
  127. data/config/application.rb +75 -0
  128. data/config/boot.rb +6 -0
  129. data/config/database.yml +17 -0
  130. data/config/deploy/roundlake-passenger.rb +3 -0
  131. data/config/deploy/roundlake-trinidad.rb +3 -0
  132. data/config/deploy.rb +37 -0
  133. data/config/environment.rb +5 -0
  134. data/config/environments/development.rb +39 -0
  135. data/config/environments/production.rb +67 -0
  136. data/config/environments/test.rb +37 -0
  137. data/config/initializers/active_admin.rb +31 -0
  138. data/config/initializers/backtrace_silencers.rb +7 -0
  139. data/config/initializers/devise.rb +232 -0
  140. data/config/initializers/inflections.rb +15 -0
  141. data/config/initializers/mime_types.rb +5 -0
  142. data/config/initializers/money.rb +6 -0
  143. data/config/initializers/redis.rb +4 -0
  144. data/config/initializers/secret_token.rb +7 -0
  145. data/config/initializers/session_store.rb +8 -0
  146. data/config/initializers/setup_rack.rb +1 -0
  147. data/config/initializers/wrap_parameters.rb +14 -0
  148. data/config/locales/active_admin.ru.yml +71 -0
  149. data/config/locales/activerecord.ru.yml +645 -0
  150. data/config/locales/devise.ru.yml +57 -0
  151. data/config/locales/ru.yml +33 -0
  152. data/config/locales/smartkiosk.gateways.ru.yml +241 -0
  153. data/config/locales/smartkiosk.hardware.ru.yml +38 -0
  154. data/config/locales/smartkiosk.reports.ru.yml +56 -0
  155. data/config/locales/smartkiosk.ru.yml +163 -0
  156. data/config/nginx.conf +9 -0
  157. data/config/redis.yml +9 -0
  158. data/config/routes.rb +48 -0
  159. data/config/schedule.rb +13 -0
  160. data/config/sidekiq.yml +5 -0
  161. data/config/trinidad.yml +6 -0
  162. data/config.ru +4 -0
  163. data/db/migrate/20120825083035_create_terminals.rb +47 -0
  164. data/db/migrate/20120825083305_create_payments.rb +51 -0
  165. data/db/migrate/20120827062618_devise_create_users.rb +50 -0
  166. data/db/migrate/20120827132621_create_admin_notes.rb +17 -0
  167. data/db/migrate/20120827132622_move_admin_notes_to_comments.rb +25 -0
  168. data/db/migrate/20120903193346_create_providers.rb +24 -0
  169. data/db/migrate/20120922075345_create_collections.rb +26 -0
  170. data/db/migrate/20120922080440_create_agents.rb +29 -0
  171. data/db/migrate/20120922081104_create_commissions.rb +10 -0
  172. data/db/migrate/20120927035841_create_gateways.rb +13 -0
  173. data/db/migrate/20120927040626_create_provider_gateways.rb +13 -0
  174. data/db/migrate/20120927091849_create_limits.rb +10 -0
  175. data/db/migrate/20120927164647_create_roles.rb +14 -0
  176. data/db/migrate/20121003131522_create_report_templates.rb +18 -0
  177. data/db/migrate/20121007135652_create_reports.rb +13 -0
  178. data/db/migrate/20121008073905_create_report_results.rb +10 -0
  179. data/db/migrate/20121017114538_create_gateway_settings.rb +12 -0
  180. data/db/migrate/20121017114556_create_gateway_attachments.rb +10 -0
  181. data/db/migrate/20121019132606_create_revisions.rb +19 -0
  182. data/db/migrate/20121023073501_create_gateway_switches.rb +10 -0
  183. data/db/migrate/20121112142743_create_terminal_orders.rb +13 -0
  184. data/db/migrate/20121118191553_create_versions.rb +19 -0
  185. data/db/migrate/20121125093414_create_system_receipt_templates.rb +9 -0
  186. data/db/migrate/20121127192257_create_terminal_builds.rb +10 -0
  187. data/db/migrate/20121212053441_create_rebates.rb +15 -0
  188. data/db/migrate/20121216143855_create_provider_receipt_templates.rb +9 -0
  189. data/db/migrate/20130101091100_create_terminal_profiles.rb +13 -0
  190. data/db/migrate/20130101091734_create_provider_rebates.rb +21 -0
  191. data/db/migrate/20130102164447_create_limit_sections.rb +14 -0
  192. data/db/migrate/20130102164503_create_commission_sections.rb +17 -0
  193. data/db/migrate/20130102171743_create_provider_profiles.rb +10 -0
  194. data/db/migrate/20130103152507_create_provider_fields.rb +17 -0
  195. data/db/migrate/20130103154526_create_provider_groups.rb +10 -0
  196. data/db/migrate/20130104063628_create_terminal_profile_providers.rb +11 -0
  197. data/db/migrate/20130104090957_create_terminal_profile_provider_groups.rb +11 -0
  198. data/db/migrate/20130108091644_create_terminal_profile_promotions.rb +10 -0
  199. data/db/schema.rb +489 -0
  200. data/db/seeds/receipt_templates/payment.txt +19 -0
  201. data/db/seeds/receipt_templates/system/balance.txt +13 -0
  202. data/db/seeds/receipt_templates/system/collection.txt +17 -0
  203. data/db/seeds/receipt_templates/system/touchtest.txt +15 -0
  204. data/db/seeds.rb +18 -0
  205. data/doc/README_FOR_APP +2 -0
  206. data/init.rb +1 -0
  207. data/lib/active_admin/cancan_integration.rb +81 -0
  208. data/lib/active_admin/form_builder_fix.rb +76 -0
  209. data/lib/active_admin/inputs/filter_date_range_input_fix.rb +24 -0
  210. data/lib/active_admin/inputs/filter_multiple_select_input.rb +18 -0
  211. data/lib/active_admin/inputs/filter_numeric_range_input.rb +31 -0
  212. data/lib/active_admin/resource_controller_fix.rb +23 -0
  213. data/lib/active_admin/views/pages/base_fix.rb +13 -0
  214. data/lib/assets/.gitkeep +0 -0
  215. data/lib/blueprints.rb +79 -0
  216. data/lib/date_expander.rb +38 -0
  217. data/lib/dav4rack/build_resource.rb +59 -0
  218. data/lib/formtastic/inputs/selectable_check_boxes.rb +39 -0
  219. data/lib/paper_trail/version_fix.rb +3 -0
  220. data/lib/report_builder.rb +88 -0
  221. data/lib/seeder.rb +103 -0
  222. data/lib/smartkiosk/server/version.rb +5 -0
  223. data/lib/smartkiosk/server.rb +35 -0
  224. data/lib/string_file.rb +12 -0
  225. data/lib/tasks/.gitkeep +0 -0
  226. data/lib/tasks/db.rake +27 -0
  227. data/lib/tasks/dump.rake +53 -0
  228. data/lib/tasks/matrioshka.rake +16 -0
  229. data/log/.gitkeep +0 -0
  230. data/log/gateways/.gitkeep +0 -0
  231. data/public/404.html +26 -0
  232. data/public/422.html +26 -0
  233. data/public/500.html +25 -0
  234. data/public/robots.txt +5 -0
  235. data/script/rails +6 -0
  236. data/smartkiosk-server.gemspec +23 -0
  237. data/spec/controllers/collections_controller_spec.rb +32 -0
  238. data/spec/controllers/payments_controller_spec.rb +123 -0
  239. data/spec/controllers/system_receipt_templates_controller_spec.rb +5 -0
  240. data/spec/controllers/terminal_builds_controller_spec.rb +5 -0
  241. data/spec/controllers/terminal_orders_controller_spec.rb +32 -0
  242. data/spec/controllers/terminal_pings_controller_spec.rb +31 -0
  243. data/spec/spec_helper.rb +66 -0
  244. data/vendor/assets/javascripts/.gitkeep +0 -0
  245. data/vendor/assets/javascripts/chosen.jquery.js +1026 -0
  246. data/vendor/assets/javascripts/datepicker-ru.jquery.js +21 -0
  247. data/vendor/assets/javascripts/nestedSortable.jquery.js +429 -0
  248. data/vendor/assets/javascripts/qtip.jquery.js +3403 -0
  249. data/vendor/assets/stylesheets/.gitkeep +0 -0
  250. data/vendor/assets/stylesheets/chosen.jquery.css +397 -0
  251. data/vendor/assets/stylesheets/modules/PIE.htc +96 -0
  252. data/vendor/assets/stylesheets/qtip.jquery.css.scss +604 -0
  253. data/vendor/plugins/.gitkeep +0 -0
  254. metadata +333 -0
@@ -0,0 +1,126 @@
1
+ require_dependency 'terminal_ping'
2
+
3
+ class Terminal < ActiveRecord::Base
4
+ include Redis::Objects::RMap
5
+
6
+ HARDWARE = %w(cash_acceptor modem printer)
7
+ ORDERS = %w(reload reboot disable enable upgrade)
8
+
9
+ has_rmap({:id => lambda{|x| x.to_s}}, :keyword)
10
+ has_paper_trail :ignore => [:incomplete_orders_count]
11
+
12
+ #
13
+ # RELATIONS
14
+ #
15
+ belongs_to :terminal_profile
16
+ belongs_to :agent
17
+ has_many :collections, :order => 'id DESC'
18
+ has_many :payments, :order => 'id DESC'
19
+ has_many :terminal_orders, :order => 'id DESC'
20
+
21
+ list :pings, :marshal => true, :maxlength => 480
22
+
23
+ scope :ok, where(:condition => 'ok')
24
+ scope :warning, where(:condition => 'warning')
25
+ scope :error, where(:condition => 'error')
26
+
27
+ #
28
+ # VALIDATIONS
29
+ #
30
+ validates :terminal_profile, :presence => true
31
+ validates :title, :presence => true
32
+ validates :keyword, :presence => true, :uniqueness => true
33
+ validates :agent, :presence => true
34
+
35
+ #
36
+ # METHODS
37
+ #
38
+ def providers_dump(after=nil)
39
+ providers = Provider.includes(:provider_fields).after(after)
40
+
41
+ return [] if providers.blank?
42
+
43
+ overload = Hash[*terminal_profile.terminal_profile_providers.map{|x| [x.provider_id, x]}.flatten]
44
+
45
+ providers.map do |x|
46
+ icon = overload[x.id].icon
47
+
48
+ if icon.blank?
49
+ icon = x.icon.try(:url)
50
+ else
51
+ icon = icon.url
52
+ end
53
+
54
+ {
55
+ :id => x.id,
56
+ :title => x.title,
57
+ :keyword => x.keyword,
58
+ :icon => icon,
59
+ :priority => overload[x.id].try(:priority),
60
+ :fields => x.fields_dump,
61
+ :group_id => x.provider_group_id,
62
+ :requires_print => x.requires_print
63
+ }
64
+ end
65
+ end
66
+
67
+ def promotions_dump
68
+ terminal_profile.terminal_profile_promotions.map{|x| x.provider_id}
69
+ end
70
+
71
+ def provider_groups_dump
72
+ overload = Hash[*terminal_profile.terminal_profile_provider_groups.map{|x| [x.provider_group_id, x]}.flatten]
73
+
74
+ ProviderGroup.all.map do |x|
75
+ icon = overload[x.id].icon
76
+
77
+ if icon.blank?
78
+ icon = x.icon.try(:url)
79
+ else
80
+ icon = icon.url
81
+ end
82
+
83
+ {
84
+ :id => x.id,
85
+ :title => x.title,
86
+ :icon => icon,
87
+ :priority => overload[x.id].try(:priority),
88
+ :parent_id => x.provider_group_id
89
+ }
90
+ end
91
+ end
92
+
93
+ def title
94
+ keyword
95
+ end
96
+
97
+ def ping!(data)
98
+ raise ActiveRecord::RecordInvalid unless data.valid?
99
+ pings.unshift data
100
+
101
+ update = {
102
+ :state => data.state,
103
+ :condition => data.condition,
104
+ :notified_at => data.created_at,
105
+ :version => data.version
106
+ }
107
+
108
+ HARDWARE.each do |device|
109
+ update["#{device}_error"] = data.error(device)
110
+ end
111
+
112
+ if data.ok?
113
+ update[:issues_started_at] = nil
114
+ else
115
+ update[:issues_started_at] = DateTime.now if issues_started_at.blank?
116
+ end
117
+
118
+ self.without_versioning do
119
+ update_attributes update
120
+ end
121
+ end
122
+
123
+ def order!(keyword, *args)
124
+ TerminalOrder.create!(:terminal_id => id, :keyword => keyword, :args => args)
125
+ end
126
+ end
@@ -0,0 +1,62 @@
1
+ require 'digest/md5'
2
+
3
+ class TerminalBuild < ActiveRecord::Base
4
+ mount_uploader :source, ZipUploader
5
+
6
+ validates :source, :presence => true
7
+ serialize :hashes
8
+
9
+ validate do
10
+ errors[:base] << I18n.t('activerecord.errors.models.terminal_build.no_version') if version.blank?
11
+ end
12
+
13
+ before_validation do
14
+ self.version = read_version
15
+ end
16
+
17
+ after_create do
18
+ Zip::ZipFile.open(source.path) do |zip_file|
19
+ zip_file.each do |f|
20
+ destination = File.join(self.path, f.name)
21
+ FileUtils.mkdir_p File.dirname(destination)
22
+ zip_file.extract(f, destination) unless File.exist?(destination)
23
+ end
24
+ end
25
+
26
+ self.update_attributes :hashes => build_hashes
27
+ end
28
+
29
+ after_destroy do
30
+ FileUtils.rm_rf path
31
+ end
32
+
33
+ def path
34
+ Rails.root.join("public/builds/#{id}").to_s
35
+ end
36
+
37
+ def url
38
+ "/builds/#{id}"
39
+ end
40
+
41
+ def read_version
42
+ return unless source.present?
43
+
44
+ Zip::ZipFile.open(source.path) do |zip_file|
45
+ return zip_file.read('VERSION').strip rescue nil
46
+ end
47
+ end
48
+
49
+ def build_hashes
50
+ files = Dir.glob("#{path}/**/**", File::FNM_DOTMATCH).select{|x| File.file? x}.map!{|x| x.gsub path+'/', ''}
51
+ hashes = {}
52
+
53
+ files.each do |file|
54
+ hashes[file] = [
55
+ Digest::MD5.file("#{path}/#{file}").hexdigest,
56
+ File.size?("#{path}/#{file}")
57
+ ]
58
+ end
59
+
60
+ hashes
61
+ end
62
+ end
@@ -0,0 +1,42 @@
1
+ class TerminalOrder < ActiveRecord::Base
2
+
3
+ has_paper_trail
4
+
5
+ belongs_to :terminal
6
+
7
+ scope :unsent, where(:state => 'new')
8
+ scope :incomplete, where("state != ?", 'complete')
9
+
10
+ validates :terminal, :presence => true
11
+
12
+ serialize :args
13
+
14
+ after_save do
15
+ terminal.update_attribute :incomplete_orders_count,
16
+ terminal.terminal_orders.incomplete.count
17
+ end
18
+
19
+ def title
20
+ I18n.t "smartkiosk.terminal_orders.#{keyword}"
21
+ end
22
+
23
+ def error?
24
+ !error.blank?
25
+ end
26
+
27
+ def sent?
28
+ state == 'sent'
29
+ end
30
+
31
+ def complete?
32
+ state == 'complete'
33
+ end
34
+
35
+ def sent!(percent=nil, error=nil)
36
+ update_attributes(:state => (complete? ? 'complete' : 'sent'), :percent => [percent.to_i, self.percent.to_i].max, :error => error)
37
+ end
38
+
39
+ def complete!
40
+ update_attribute(:state, 'complete')
41
+ end
42
+ end
@@ -0,0 +1,120 @@
1
+ class TerminalPing
2
+ include ActiveAttr::Model
3
+ include ActiveModel::Translation
4
+ include ActiveModel::Callbacks
5
+ extend Machinist::Machinable
6
+
7
+ def self.i18n_scope
8
+ :activerecord
9
+ end
10
+
11
+ attribute :state, :type => String, :default => 'unknown'
12
+ attribute :condition, :type => String
13
+ attribute :version
14
+ attribute :ip, :type => String
15
+
16
+ # '100' => 1, '1000' => 5
17
+ attribute :banknotes, :default => {}
18
+
19
+ # :error => '...', :version => '...'
20
+ attribute :cash_acceptor, :default => {}
21
+
22
+ # :error => '', :version => ''
23
+ attribute :printer, :default => {}
24
+
25
+ # :error => '', :version => '', :signal_level => 4, :balance => 54.5
26
+ attribute :modem, :default => {}
27
+
28
+ # :payments => 5, :orders => 4
29
+ attribute :queues, :default => {}
30
+
31
+ attribute :created_at, :type => DateTime, :default => proc { DateTime.now }
32
+
33
+ def value(field, hardware)
34
+ source = (send(hardware) || {}) rescue {}
35
+ source[field].blank? ? nil : source[field]
36
+ end
37
+
38
+ def error(*hardware)
39
+ if hardware.count == 1
40
+ v = value('error', hardware.first)
41
+ return v.nil? ? nil : v.to_i
42
+ else
43
+ return hardware.map do |x|
44
+ v = value('error', x)
45
+ v.nil? ? nil : v.to_i
46
+ end
47
+ end
48
+ end
49
+
50
+ def valid?(*args)
51
+ codes = error(*Terminal::HARDWARE).compact
52
+
53
+ self.condition =
54
+ if codes.blank?
55
+ 'ok'
56
+ elsif codes.min >= 1000
57
+ 'warning'
58
+ else
59
+ 'error'
60
+ end
61
+
62
+ super
63
+ end
64
+
65
+ def ok?
66
+ condition == 'ok'
67
+ end
68
+
69
+ def cash_sum
70
+ banknotes.collect{|k,v| k.to_i*v.to_i}.sum
71
+ end
72
+
73
+ def cash_count
74
+ banknotes.values.map{|x| x.to_i}.sum
75
+ end
76
+
77
+ def cash_acceptor_error
78
+ error(:cash_acceptor)
79
+ end
80
+
81
+ def cash_acceptor_version
82
+ value 'version', :cash_acceptor
83
+ end
84
+
85
+ def cash_acceptor_model
86
+ value 'model', :cash_acceptor
87
+ end
88
+
89
+ def printer_error
90
+ error(:printer)
91
+ end
92
+
93
+ def printer_version
94
+ value 'version', :printer
95
+ end
96
+
97
+ def printer_model
98
+ value 'model', :printer
99
+ end
100
+
101
+ def modem_error
102
+ error(:modem)
103
+ end
104
+
105
+ def modem_version
106
+ value 'version', :modem
107
+ end
108
+
109
+ def modem_balance
110
+ modem['balance']
111
+ end
112
+
113
+ def modem_signal_level
114
+ modem['signal_level']
115
+ end
116
+
117
+ def modem_model
118
+ value 'model', :modem
119
+ end
120
+ end
@@ -0,0 +1,51 @@
1
+ class TerminalProfile < ActiveRecord::Base
2
+ include Redis::Objects::RMap
3
+
4
+ has_rmap({:id => lambda{|x| x.to_s}}, :keyword)
5
+ has_paper_trail
6
+
7
+ has_many :terminals, :conditions => "terminal_profile_id IS NOT NULL"
8
+ has_many :terminal_profile_promotions, :dependent => :destroy, :order => :priority
9
+ has_many :terminal_profile_providers, :dependent => :destroy, :order => :priority
10
+ has_many :terminal_profile_provider_groups, :dependent => :destroy, :order => :priority
11
+
12
+ mount_uploader :logo, FileUploader
13
+
14
+ accepts_nested_attributes_for :terminal_profile_promotions, :allow_destroy => true
15
+ accepts_nested_attributes_for :terminal_profile_providers
16
+ accepts_nested_attributes_for :terminal_profile_provider_groups
17
+
18
+ def terminal_profile_provider_groups(parent=false)
19
+ data = TerminalProfileProviderGroup.where(:terminal_profile_id => id).
20
+ includes(:provider_group => :provider_group).order(:priority)
21
+
22
+ data = data.where(:provider_groups => {:provider_group_id => parent}) unless parent === false
23
+ pgids = data.map{|x| x.provider_group_id}
24
+
25
+ ProviderGroup.all.each do |pg|
26
+ unless pgids.include?(pg.id)
27
+ data << TerminalProfileProviderGroup.new(:provider_group_id => pg.id, :terminal_profile_id => id)
28
+ end
29
+ end
30
+
31
+ data
32
+ end
33
+
34
+ def terminal_profile_providers(category=nil)
35
+ category = category.id if !category.blank? && category.respond_to?(:id)
36
+ search = category.nil? ? {} : {:provider_group_id => category}
37
+
38
+ data = TerminalProfileProvider.includes(:provider).
39
+ where(:terminal_profile_id => id, :providers => search).
40
+ order("terminal_profile_providers.priority")
41
+ pids = data.map{|x| x.provider_id}
42
+
43
+ Provider.where(search).all.each do |p|
44
+ unless pids.include?(p.id)
45
+ data << TerminalProfileProvider.new(:provider_id => p.id, :terminal_profile_id => id)
46
+ end
47
+ end
48
+
49
+ data
50
+ end
51
+ end
@@ -0,0 +1,18 @@
1
+ class TerminalProfilePromotion < ActiveRecord::Base
2
+ include Redis::Objects::RMap
3
+
4
+ value :timestamp, :global => true, :marshal => true
5
+
6
+ belongs_to :terminal_profile
7
+ belongs_to :provider
8
+
9
+ validates :provider, :presence => true
10
+
11
+ after_save do
12
+ self.class.timestamp = updated_at
13
+ end
14
+
15
+ after_destroy do
16
+ self.class.timestamp = DateTime.now
17
+ end
18
+ end
@@ -0,0 +1,11 @@
1
+ class TerminalProfileProvider < ActiveRecord::Base
2
+
3
+ mount_uploader :icon, IconUploader
4
+
5
+ belongs_to :provider
6
+ belongs_to :terminal_profile, :inverse_of => :terminal_profile_providers
7
+
8
+ validates :provider_id, :uniqueness => {:scope => :terminal_profile_id}
9
+ validates :provider, :presence => true
10
+ validates :terminal_profile, :presence => true
11
+ end
@@ -0,0 +1,19 @@
1
+ class TerminalProfileProviderGroup < ActiveRecord::Base
2
+
3
+ self.table_name = 'term_prof_provider_groups'
4
+
5
+ mount_uploader :icon, IconUploader
6
+
7
+ belongs_to :provider_group
8
+ belongs_to :terminal_profile, :inverse_of => :terminal_profile_provider_groups
9
+
10
+ validates :provider_group_id, :uniqueness => {:scope => :terminal_profile_id}
11
+ validates :provider_group, :presence => true
12
+ validates :terminal_profile, :presence => true
13
+
14
+ delegate :title, :to => :terminal_profile
15
+
16
+ def terminal_profile_providers
17
+ terminal_profile.terminal_profile_providers(provider_group_id)
18
+ end
19
+ end
@@ -0,0 +1,38 @@
1
+ class User < ActiveRecord::Base
2
+
3
+ has_paper_trail
4
+
5
+ devise :database_authenticatable,
6
+ :recoverable, :rememberable, :trackable, :validatable
7
+
8
+ #
9
+ # RELATIONS
10
+ #
11
+ has_many :user_roles
12
+ has_many :roles, :through => :user_roles
13
+
14
+ accepts_nested_attributes_for :user_roles, :allow_destroy => true
15
+
16
+ #
17
+ # VALIDATIONS
18
+ #
19
+ validates :full_name, :presence => true
20
+
21
+ #
22
+ # METHODS
23
+ #
24
+ def role?(role)
25
+ return true if root
26
+ return roles.map{|x| x.keyword}.include? role.to_s
27
+ end
28
+
29
+ def priveleged?(role, action)
30
+ return true if root
31
+ ur = user_roles.includes(:role).find{|x| x.role.keyword == role.to_s}
32
+ ur.blank? ? false : ur.priveleged?(action)
33
+ end
34
+
35
+ def title
36
+ email
37
+ end
38
+ end
@@ -0,0 +1,45 @@
1
+ class UserRole < ActiveRecord::Base
2
+ belongs_to :user
3
+ belongs_to :role
4
+
5
+ serialize :priveleges
6
+
7
+ validates :role, :presence => true
8
+
9
+ def method_missing(method, *args)
10
+ method = method.to_s
11
+
12
+ if method.starts_with? 'can_'
13
+ role_keyword = method[method.index('_')+1..method.rindex('_')-1]
14
+ privelege = method[method.rindex('_')+1..-1]
15
+
16
+ self.priveleges = [] unless self.priveleges.is_a?(Array)
17
+
18
+ if method.ends_with? '='
19
+ privelege = privelege[0..-2]
20
+
21
+ if role && role.keyword == role_keyword
22
+ if args[0] && args[0] != 'false'
23
+ self.priveleges = (self.priveleges + [privelege]).uniq
24
+ else
25
+ self.priveleges = self.priveleges.select{|x| x != privelege}
26
+ end
27
+ end
28
+ else
29
+ return false if !role || role.keyword != role_keyword
30
+ self.priveleges.include?(privelege)
31
+ end
32
+ else
33
+ super(method.to_sym, *args)
34
+ end
35
+ end
36
+
37
+ def respond_to?(method, *args)
38
+ return true if method.to_s.starts_with? 'can_'
39
+ super
40
+ end
41
+
42
+ def priveleged?(privelege)
43
+ priveleges.include?(privelege.to_s)
44
+ end
45
+ end
@@ -0,0 +1,81 @@
1
+ # coding: utf-8
2
+
3
+ class AgentsReport < ReportBuilder::Base
4
+ def tables
5
+ @tables ||= {
6
+ :agent => Arel::Table.new(:agents),
7
+ :parent_agent => Arel::Table.new(:agents).alias("parent_agents")
8
+ }.with_indifferent_access
9
+ end
10
+
11
+ def context(start, finish)
12
+ context = tables[:agent]
13
+ context = context.join(tables[:parent_agent], Arel::Nodes::OuterJoin).on(tables[:agent][:agent_id].eq tables[:parent_agent][:id])
14
+ context = context.where(tables[:agent][:created_at].in(start..finish)) if !start.blank? || !finish.blank?
15
+ context
16
+ end
17
+
18
+ def groupping
19
+ %w(
20
+ agent.agent_id
21
+ )
22
+ end
23
+
24
+ def fields
25
+ {
26
+ '' => %w(
27
+ agent.title
28
+ agent.juristic_name
29
+ agent.juristic_address_city
30
+ agent.juristic_address_street
31
+ agent.juristic_address_home
32
+ agent.physical_address_city
33
+ agent.physical_address_district
34
+ agent.physical_address_subway
35
+ agent.physical_address_street
36
+ agent.physical_address_home
37
+ agent.contact_name
38
+ agent.contact_info
39
+ agent.director_name
40
+ agent.director_contact_info
41
+ agent.bookkeeper_name
42
+ agent.bookkeeper_contact_info
43
+ agent.inn
44
+ agent.support_phone
45
+ ),
46
+ 'agent.agent_id' => %w(
47
+ agent.agent_id
48
+ parent_agent.title
49
+ parent_agent.juristic_name
50
+ parent_agent.juristic_address_city
51
+ parent_agent.juristic_address_street
52
+ parent_agent.juristic_address_home
53
+ parent_agent.physical_address_city
54
+ parent_agent.physical_address_district
55
+ parent_agent.physical_address_subway
56
+ parent_agent.physical_address_street
57
+ parent_agent.physical_address_home
58
+ parent_agent.contact_name
59
+ parent_agent.contact_info
60
+ parent_agent.director_name
61
+ parent_agent.director_contact_info
62
+ parent_agent.bookkeeper_name
63
+ parent_agent.bookkeeper_contact_info
64
+ parent_agent.inn
65
+ parent_agent.support_phone
66
+ )
67
+ }
68
+ end
69
+
70
+ def calculations
71
+ {
72
+ :quantity => lambda{|q, t| t.groupping.blank? ? q : q.project('COUNT(*) AS "calculations.quantity"').where(tables[:agent][:agent_id].not_eq nil) }
73
+ }.with_indifferent_access
74
+ end
75
+
76
+ def conditions
77
+ {
78
+ 'agent.agent_id' => proc{ Agent.rmap.invert }
79
+ }
80
+ end
81
+ end