voluntary 0.0.1

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 (295) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.rdoc +48 -0
  3. data/Rakefile +27 -0
  4. data/app/assets/javascripts/voluntary/application.js +6 -0
  5. data/app/assets/javascripts/voluntary/base.js.coffee +34 -0
  6. data/app/assets/javascripts/voluntary/bootstrap.js.coffee +4 -0
  7. data/app/assets/javascripts/voluntary/functions.js +24 -0
  8. data/app/assets/javascripts/voluntary/users.js.coffee +12 -0
  9. data/app/assets/stylesheets/voluntary/application.css +15 -0
  10. data/app/assets/stylesheets/voluntary/base.css.scss +40 -0
  11. data/app/assets/stylesheets/voluntary/bootstrap_and_overrides.css.less +67 -0
  12. data/app/controllers/areas_controller.rb +66 -0
  13. data/app/controllers/candidatures_controller.rb +79 -0
  14. data/app/controllers/comments_controller.rb +70 -0
  15. data/app/controllers/devise_extensions/registrations_controller.rb +37 -0
  16. data/app/controllers/home_controller.rb +7 -0
  17. data/app/controllers/organizations_controller.rb +67 -0
  18. data/app/controllers/pages_controller.rb +54 -0
  19. data/app/controllers/products_controller.rb +62 -0
  20. data/app/controllers/professions_controller.rb +66 -0
  21. data/app/controllers/projects_controller.rb +56 -0
  22. data/app/controllers/results_controller.rb +93 -0
  23. data/app/controllers/stories_controller.rb +96 -0
  24. data/app/controllers/tasks_controller.rb +88 -0
  25. data/app/controllers/users_controller.rb +52 -0
  26. data/app/controllers/vacancies_controller.rb +79 -0
  27. data/app/controllers/voluntary/application_controller.rb +92 -0
  28. data/app/controllers/workflow/candidatures_controller.rb +20 -0
  29. data/app/controllers/workflow/products_controller.rb +6 -0
  30. data/app/controllers/workflow/project_owner_controller.rb +33 -0
  31. data/app/controllers/workflow/stories_controller.rb +6 -0
  32. data/app/controllers/workflow/tasks_controller.rb +147 -0
  33. data/app/controllers/workflow/user_controller.rb +6 -0
  34. data/app/controllers/workflow/vacancies_controller.rb +17 -0
  35. data/app/controllers/workflow_controller.rb +7 -0
  36. data/app/helpers/application_helper.rb +65 -0
  37. data/app/helpers/collection_helper.rb +31 -0
  38. data/app/helpers/comments_helper.rb +11 -0
  39. data/app/helpers/form_helper.rb +39 -0
  40. data/app/helpers/language_helper.rb +15 -0
  41. data/app/helpers/layout_helper.rb +24 -0
  42. data/app/helpers/product_helper.rb +32 -0
  43. data/app/helpers/show_helper.rb +65 -0
  44. data/app/helpers/wizard_helper.rb +27 -0
  45. data/app/models/area.rb +19 -0
  46. data/app/models/area_user.rb +19 -0
  47. data/app/models/candidature.rb +35 -0
  48. data/app/models/comment.rb +16 -0
  49. data/app/models/history_tracker.rb +3 -0
  50. data/app/models/mongo_db_document.rb +11 -0
  51. data/app/models/organization.rb +19 -0
  52. data/app/models/page.rb +30 -0
  53. data/app/models/product.rb +99 -0
  54. data/app/models/product/new_product.rb +3 -0
  55. data/app/models/product/project_management.rb +29 -0
  56. data/app/models/profession.rb +13 -0
  57. data/app/models/project.rb +66 -0
  58. data/app/models/project_user.rb +13 -0
  59. data/app/models/result.rb +55 -0
  60. data/app/models/role.rb +8 -0
  61. data/app/models/role/admin.rb +2 -0
  62. data/app/models/role/master.rb +2 -0
  63. data/app/models/role/project_owner.rb +2 -0
  64. data/app/models/role/user.rb +2 -0
  65. data/app/models/state_machines/candidature.rb +42 -0
  66. data/app/models/state_machines/page.rb +18 -0
  67. data/app/models/state_machines/story.rb +51 -0
  68. data/app/models/state_machines/task.rb +46 -0
  69. data/app/models/state_machines/vacancy.rb +41 -0
  70. data/app/models/story.rb +82 -0
  71. data/app/models/task.rb +85 -0
  72. data/app/models/user.rb +95 -0
  73. data/app/models/user_role.rb +6 -0
  74. data/app/models/vacancy.rb +41 -0
  75. data/app/observers/candidature_observer.rb +29 -0
  76. data/app/observers/story_observer.rb +6 -0
  77. data/app/observers/task_observer.rb +34 -0
  78. data/app/presenters/layout/application_presenter.rb +3 -0
  79. data/app/presenters/layout_presenter.rb +9 -0
  80. data/app/presenters/presenter.rb +46 -0
  81. data/app/presenters/resource_presenter.rb +30 -0
  82. data/app/presenters/resources/general/wizard_presenter.rb +17 -0
  83. data/app/presenters/resources/general/wizards/story/steps/activate_presenter.rb +3 -0
  84. data/app/presenters/resources/general/wizards/story/steps/setup_tasks_presenter.rb +5 -0
  85. data/app/presenters/resources/general/wizards/story_presenter.rb +3 -0
  86. data/app/presenters/resources/user/form_presenter.rb +16 -0
  87. data/app/presenters/shared/collection/table_presenter.rb +33 -0
  88. data/app/views/areas/_form.html.erb +11 -0
  89. data/app/views/areas/edit.html.erb +3 -0
  90. data/app/views/areas/index.html.erb +5 -0
  91. data/app/views/areas/new.html.erb +3 -0
  92. data/app/views/areas/show.html.erb +6 -0
  93. data/app/views/candidatures/_form.html.erb +13 -0
  94. data/app/views/candidatures/edit.html.erb +3 -0
  95. data/app/views/candidatures/index.html.erb +11 -0
  96. data/app/views/candidatures/new.html.erb +3 -0
  97. data/app/views/candidatures/show.html.erb +18 -0
  98. data/app/views/comments/_form.html.erb +16 -0
  99. data/app/views/comments/_resource.html.erb +16 -0
  100. data/app/views/comments/edit.html.erb +3 -0
  101. data/app/views/comments/new.html.erb +3 -0
  102. data/app/views/devise/mailer/confirmation_instructions.html.erb +10 -0
  103. data/app/views/devise/registrations/new.html.erb +5 -0
  104. data/app/views/general/wizard.html.erb +16 -0
  105. data/app/views/kaminari/_first_page.html.erb +13 -0
  106. data/app/views/kaminari/_gap.html.erb +8 -0
  107. data/app/views/kaminari/_last_page.html.erb +13 -0
  108. data/app/views/kaminari/_next_page.html.erb +13 -0
  109. data/app/views/kaminari/_page.html.erb +12 -0
  110. data/app/views/kaminari/_paginator.html.erb +25 -0
  111. data/app/views/kaminari/_prev_page.html.erb +13 -0
  112. data/app/views/layouts/application.html.erb +48 -0
  113. data/app/views/layouts/shared/_flash_messages.html.erb +7 -0
  114. data/app/views/layouts/shared/_navigation.html.erb +7 -0
  115. data/app/views/organizations/_form.html.erb +11 -0
  116. data/app/views/organizations/edit.html.erb +3 -0
  117. data/app/views/organizations/index.html.erb +5 -0
  118. data/app/views/organizations/new.html.erb +3 -0
  119. data/app/views/organizations/show.html.erb +6 -0
  120. data/app/views/pages/_form.html.erb +12 -0
  121. data/app/views/pages/edit.html.erb +3 -0
  122. data/app/views/pages/index.html.erb +5 -0
  123. data/app/views/pages/new.html.erb +3 -0
  124. data/app/views/pages/show.html.erb +10 -0
  125. data/app/views/products/_form.html.erb +28 -0
  126. data/app/views/products/edit.html.erb +3 -0
  127. data/app/views/products/index.html.erb +5 -0
  128. data/app/views/products/mixins/_keywords.html.erb +4 -0
  129. data/app/views/products/new.html.erb +3 -0
  130. data/app/views/products/show.html.erb +11 -0
  131. data/app/views/products/types/text_creation/stories/_form.html.erb +19 -0
  132. data/app/views/products/types/text_creation/stories/_task_fields.html.erb +7 -0
  133. data/app/views/projects/_form.html.erb +16 -0
  134. data/app/views/projects/edit.html.erb +3 -0
  135. data/app/views/projects/index.html.erb +5 -0
  136. data/app/views/projects/new.html.erb +3 -0
  137. data/app/views/projects/show.html.erb +13 -0
  138. data/app/views/shared/_comments.html.erb +7 -0
  139. data/app/views/shared/collection/_list.html.erb +37 -0
  140. data/app/views/shared/collection/_table.html.erb +36 -0
  141. data/app/views/shared/form/_error_messages.html.erb +10 -0
  142. data/app/views/shared/resource/_actions.html.erb +26 -0
  143. data/app/views/shared/resource/_event_elements.html.erb +7 -0
  144. data/app/views/stories/_collection.html.erb +8 -0
  145. data/app/views/stories/_form.html.erb +19 -0
  146. data/app/views/stories/_task_fields.html.erb +11 -0
  147. data/app/views/stories/index.html.erb +1 -0
  148. data/app/views/stories/show.html.erb +13 -0
  149. data/app/views/stories/steps/_activate.html.erb +17 -0
  150. data/app/views/stories/steps/_setup_tasks.html.erb +35 -0
  151. data/app/views/stories/tasks.html.erb +0 -0
  152. data/app/views/tasks/_collection.html.erb +12 -0
  153. data/app/views/users/_form.html.erb +43 -0
  154. data/app/views/users/edit.html.erb +3 -0
  155. data/app/views/users/index.html.erb +6 -0
  156. data/app/views/users/new.html.erb +3 -0
  157. data/app/views/users/preferences.html.erb +11 -0
  158. data/app/views/users/show.html.erb +6 -0
  159. data/app/views/vacancies/_form.html.erb +15 -0
  160. data/app/views/vacancies/edit.html.erb +3 -0
  161. data/app/views/vacancies/index.html.erb +7 -0
  162. data/app/views/vacancies/new.html.erb +3 -0
  163. data/app/views/vacancies/show.html.erb +17 -0
  164. data/app/views/workflow/index.html.erb +0 -0
  165. data/app/views/workflow/products/show.html.erb +34 -0
  166. data/app/views/workflow/project_owner/_candidatures.html.erb +31 -0
  167. data/app/views/workflow/project_owner/_stories.html.erb +29 -0
  168. data/app/views/workflow/project_owner/_tasks.html.erb +34 -0
  169. data/app/views/workflow/project_owner/_vacancies.html.erb +27 -0
  170. data/app/views/workflow/project_owner/index.html.erb +24 -0
  171. data/app/views/workflow/tasks/_work_form.html.erb +8 -0
  172. data/app/views/workflow/tasks/_work_head.html.erb +15 -0
  173. data/app/views/workflow/tasks/edit.html.erb +3 -0
  174. data/app/views/workflow/tasks/index.html.erb +31 -0
  175. data/app/views/workflow/tasks/next.html.erb +0 -0
  176. data/app/views/workflow/tasks/steps/_complete.html.erb +11 -0
  177. data/app/views/workflow/tasks/steps/_review.html.erb +13 -0
  178. data/app/views/workflow/tasks/steps/_work.html.erb +17 -0
  179. data/app/views/workflow/user/_tasks.html.erb +30 -0
  180. data/app/views/workflow/user/index.html.erb +14 -0
  181. data/config/initializers/1_initialize_app_config.rb +5 -0
  182. data/config/initializers/devise.rb +193 -0
  183. data/config/initializers/locale_settings.rb +42 -0
  184. data/config/initializers/mongoid-history.rb +2 -0
  185. data/config/initializers/recaptcha.rb +7 -0
  186. data/config/initializers/simple_form.rb +178 -0
  187. data/config/initializers/simple_navigation.rb +2 -0
  188. data/config/locales/devise.en.yml +59 -0
  189. data/config/locales/en.yml +26 -0
  190. data/config/locales/general/en.yml +71 -0
  191. data/config/locales/resources/area/en.yml +12 -0
  192. data/config/locales/resources/candidature/en.yml +19 -0
  193. data/config/locales/resources/comment/en.yml +11 -0
  194. data/config/locales/resources/organization/en.yml +11 -0
  195. data/config/locales/resources/page/en.yml +11 -0
  196. data/config/locales/resources/product/en.yml +23 -0
  197. data/config/locales/resources/project/en.yml +9 -0
  198. data/config/locales/resources/result/en.yml +9 -0
  199. data/config/locales/resources/story/en.yml +34 -0
  200. data/config/locales/resources/task/en.yml +36 -0
  201. data/config/locales/resources/user/en.yml +14 -0
  202. data/config/locales/resources/vacancy/en.yml +29 -0
  203. data/config/locales/simple_form.en.yml +26 -0
  204. data/config/locales/workflow/en.yml +37 -0
  205. data/config/routes.rb +188 -0
  206. data/db/migrate/20120907144853_create_schema.rb +217 -0
  207. data/db/migrate/20120911093743_remove_timestamps_from_habtm_tables.rb +21 -0
  208. data/db/migrate/20120919161831_add_unique_index_for_one_user_candidature_per_vacancy.rb +9 -0
  209. data/db/migrate/20120922201955_create_mongo_db_documents.rb +13 -0
  210. data/db/migrate/20120923140109_add_product_to_project.rb +6 -0
  211. data/db/migrate/20121004061413_add_extra_user_attributes.rb +9 -0
  212. data/db/migrate/20121004132105_create_professions.rb +13 -0
  213. data/db/migrate/20121006162913_add_public_attribute_to_roles.rb +6 -0
  214. data/db/migrate/20121006170407_add_type_attribute_to_roles.rb +5 -0
  215. data/db/migrate/20121007071543_add_foreign_languages_to_user.rb +6 -0
  216. data/db/migrate/20121028073712_create_organizations.rb +13 -0
  217. data/db/seeds.rb +14 -0
  218. data/lib/applicat/mvc/controller.rb +171 -0
  219. data/lib/applicat/mvc/controller/error_handling.rb +40 -0
  220. data/lib/applicat/mvc/controller/resource.rb +19 -0
  221. data/lib/applicat/mvc/controller/transition_actions.rb +43 -0
  222. data/lib/applicat/mvc/model/resource/base.rb +56 -0
  223. data/lib/applicat/mvc/model/tokenable.rb +24 -0
  224. data/lib/applicat/mvc/model/tree.rb +82 -0
  225. data/lib/db_seed.rb +150 -0
  226. data/lib/environment_configuration.rb +54 -0
  227. data/lib/generators/voluntary/install/install_generator.rb +118 -0
  228. data/lib/generators/voluntary/install/templates/app/controllers/application_controller.rb +3 -0
  229. data/lib/generators/voluntary/install/templates/app/models/ability.rb +49 -0
  230. data/lib/generators/voluntary/install/templates/app/models/app_config.rb +32 -0
  231. data/lib/generators/voluntary/install/templates/app/views/layouts/application.html.erb +50 -0
  232. data/lib/generators/voluntary/install/templates/config/application.yml +147 -0
  233. data/lib/generators/voluntary/install/templates/config/cucumber.yml +8 -0
  234. data/lib/generators/voluntary/install/templates/config/database.example.yml +28 -0
  235. data/lib/generators/voluntary/install/templates/config/deploy.rb +59 -0
  236. data/lib/generators/voluntary/install/templates/config/email.example.yml +9 -0
  237. data/lib/generators/voluntary/install/templates/config/initializers/recaptcha_example +4 -0
  238. data/lib/generators/voluntary/install/templates/config/locale_settings.yml +121 -0
  239. data/lib/generators/voluntary/install/templates/config/main_navigation.rb +262 -0
  240. data/lib/generators/voluntary/install/templates/config/mongoid.yml +78 -0
  241. data/lib/generators/voluntary/install/templates/config/nginx.conf +27 -0
  242. data/lib/generators/voluntary/install/templates/config/unicorn.rb +9 -0
  243. data/lib/generators/voluntary/install/templates/config/unicorn_init.sh +84 -0
  244. data/lib/generators/voluntary/install/templates/db/seeds.rb +14 -0
  245. data/lib/generators/voluntary/install/templates/features/step_definitions/email_steps.rb +89 -0
  246. data/lib/generators/voluntary/install/templates/features/step_definitions/factory_steps.rb +120 -0
  247. data/lib/generators/voluntary/install/templates/features/step_definitions/javascript_steps.rb +15 -0
  248. data/lib/generators/voluntary/install/templates/features/step_definitions/navigation_steps.rb +3 -0
  249. data/lib/generators/voluntary/install/templates/features/step_definitions/resources_steps.rb +8 -0
  250. data/lib/generators/voluntary/install/templates/features/step_definitions/session_steps.rb +35 -0
  251. data/lib/generators/voluntary/install/templates/features/step_definitions/web_steps.rb +271 -0
  252. data/lib/generators/voluntary/install/templates/features/support/database_cleaner_patches.rb +24 -0
  253. data/lib/generators/voluntary/install/templates/features/support/env.rb +83 -0
  254. data/lib/generators/voluntary/install/templates/features/support/integration_sessions_controller.rb +32 -0
  255. data/lib/generators/voluntary/install/templates/features/support/integration_sessions_form.html.erb +1 -0
  256. data/lib/generators/voluntary/install/templates/features/support/paths.rb +98 -0
  257. data/lib/generators/voluntary/install/templates/features/support/selectors.rb +44 -0
  258. data/lib/generators/voluntary/install/templates/features/support/spork_env +72 -0
  259. data/lib/generators/voluntary/install/templates/features/support/user_cuke_helpers.rb +78 -0
  260. data/lib/generators/voluntary/install/templates/lib/volontariat_seed.rb +36 -0
  261. data/lib/generators/voluntary/install/templates/spec/spec_helper.rb +72 -0
  262. data/lib/generators/voluntary/install/templates/spec/support/deferred_garbage_collector.rb +45 -0
  263. data/lib/generators/voluntary/install/templates/spec/support/devise.rb +3 -0
  264. data/lib/generators/voluntary/install/templates/spec/support/mongo_database_cleaner.rb +19 -0
  265. data/lib/generators/voluntary/install/templates/vendor/assets/javascripts/jquery.tokeninput.js +915 -0
  266. data/lib/generators/voluntary/install/templates/vendor/assets/stylesheets/token-input-facebook.css +122 -0
  267. data/lib/generators/voluntary/install/templates/vendor/assets/stylesheets/token-input-mac.css +204 -0
  268. data/lib/generators/voluntary/install/templates/vendor/assets/stylesheets/token-input.css +127 -0
  269. data/lib/i18n_interpolation_fallbacks.rb +21 -0
  270. data/lib/model/mongo_db/commentable.rb +17 -0
  271. data/lib/model/mongo_db/core_extensions.rb +10 -0
  272. data/lib/model/mongo_db/customizable.rb +23 -0
  273. data/lib/model/mongo_db/product/keywords.rb +31 -0
  274. data/lib/model/mongo_db/state_version_attributes.rb +15 -0
  275. data/lib/tasks/cucumber.rake +65 -0
  276. data/lib/tasks/voluntary_tasks.rake +4 -0
  277. data/lib/vendors/active_model/naming.rb +14 -0
  278. data/lib/vendors/simple_navigation/renderer/breadcrumbs_without_method_links.rb +30 -0
  279. data/lib/vendors/simple_navigation/renderer/twitter_sidenav.rb +34 -0
  280. data/lib/voluntary.rb +87 -0
  281. data/lib/voluntary/engine.rb +11 -0
  282. data/lib/voluntary/helpers/application.rb +69 -0
  283. data/lib/voluntary/helpers/collection.rb +35 -0
  284. data/lib/voluntary/helpers/comments.rb +15 -0
  285. data/lib/voluntary/helpers/form.rb +43 -0
  286. data/lib/voluntary/helpers/language.rb +19 -0
  287. data/lib/voluntary/helpers/layout.rb +28 -0
  288. data/lib/voluntary/helpers/product.rb +36 -0
  289. data/lib/voluntary/helpers/show.rb +69 -0
  290. data/lib/voluntary/helpers/wizard.rb +31 -0
  291. data/lib/voluntary/version.rb +3 -0
  292. data/lib/wizard.rb +58 -0
  293. data/lib/wizard/controller/concerns/paths.rb +31 -0
  294. data/lib/wizard/controller/concerns/steps.rb +142 -0
  295. metadata +1217 -0
@@ -0,0 +1,8 @@
1
+ class Role < ActiveRecord::Base
2
+ has_many :users, through: :user_roles
3
+ has_many :projects, through: :project_users
4
+
5
+ scope :public, where(public: true)
6
+
7
+ attr_accessible :name, :public
8
+ end
@@ -0,0 +1,2 @@
1
+ class Role::Admin < Role
2
+ end
@@ -0,0 +1,2 @@
1
+ class Role::Master < Role
2
+ end
@@ -0,0 +1,2 @@
1
+ class Role::ProjectOwner < Role
2
+ end
@@ -0,0 +1,2 @@
1
+ class Role::User < Role
2
+ end
@@ -0,0 +1,42 @@
1
+ module StateMachines::Candidature
2
+ def self.included(base)
3
+ base.extend ClassMethods
4
+
5
+ base.class_eval do
6
+ attr_accessor :current_user
7
+
8
+ const_set 'STATES', [:new, :accepted, :denied]
9
+ const_set 'EVENTS', [:accept, :deny, :quit]
10
+
11
+ state_machine :state, initial: :new do
12
+ event :accept do
13
+ transition [:new, :denied] => :accepted
14
+ end
15
+
16
+ state :accepted do
17
+ validate :candidatures_limit_not_reached
18
+ end
19
+
20
+ event :deny do
21
+ transition :new => :denied
22
+ end
23
+
24
+ event :quit do
25
+ transition :accepted => :denied
26
+ end
27
+ end
28
+
29
+ private
30
+
31
+ # state validations
32
+ def candidatures_limit_not_reached
33
+ if vacancy.limit == vacancy.candidatures.where(state: 'accepted').count
34
+ errors[:state] << I18n.t('activerecord.errors.models.vacancy.attributes.limit.reached')
35
+ end
36
+ end
37
+ end
38
+ end
39
+
40
+ module ClassMethods
41
+ end
42
+ end
@@ -0,0 +1,18 @@
1
+ module StateMachines::Page
2
+ def self.included(base)
3
+ base.extend ClassMethods
4
+
5
+ base.class_eval do
6
+ attr_accessor :current_user
7
+
8
+ const_set 'STATES', [:active]
9
+ const_set 'EVENTS', []
10
+
11
+ state_machine :state, initial: :active do
12
+ end
13
+ end
14
+ end
15
+
16
+ module ClassMethods
17
+ end
18
+ end
@@ -0,0 +1,51 @@
1
+ module StateMachines::Story
2
+ def self.included(base)
3
+ base.extend ClassMethods
4
+
5
+ base.class_eval do
6
+ include Model::MongoDb::StateVersionAttributes
7
+
8
+ attr_accessor :current_user
9
+
10
+ const_set 'STATES', [:new, :tasks_defined, :active, :completed, :closed]
11
+ const_set 'EVENTS', [:initialization, :setup_tasks, :activate, :complete]
12
+
13
+ state_machine :state, initial: :new do
14
+ event :initialization do
15
+ transition :new => :initialized
16
+ end
17
+
18
+ event :setup_tasks do
19
+ transition :initialized => :tasks_defined
20
+ end
21
+
22
+ state :tasks_defined do
23
+ validates_associated :tasks
24
+ validate :presence_of_tasks
25
+ end
26
+
27
+ event :activate do
28
+ transition [:tasks_defined, :completed] => :active
29
+ end
30
+
31
+ event :complete do
32
+ transition :active => :completed
33
+ end
34
+
35
+ event :close do
36
+ transition :completed => :closed
37
+ end
38
+ end
39
+
40
+ private
41
+
42
+ def presence_of_tasks
43
+ unless tasks.any?
44
+ errors[:base] << I18n.t(
45
+ 'activerecord.errors.models.story.attributes.base.missing_tasks'
46
+ )
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,46 @@
1
+ module StateMachines::Task
2
+ def self.included(base)
3
+ base.extend ClassMethods
4
+
5
+ base.class_eval do
6
+ include Model::MongoDb::StateVersionAttributes
7
+
8
+ attr_accessor :current_user
9
+
10
+ const_set 'STATES', [:new, :assigned, :under_supervision, :completed]
11
+ const_set 'EVENTS', [:assign, :cancel, :review, :follow_up, :complete]
12
+
13
+ state_machine :state, initial: :new do
14
+ event :assign do
15
+ transition :new => :assigned
16
+ end
17
+
18
+ state :assigned do
19
+ validates :user_id, presence: true
20
+ end
21
+
22
+ event :cancel do
23
+ transition :assigned => :new
24
+ end
25
+
26
+ event :review do
27
+ transition :assigned => :under_supervision
28
+ end
29
+
30
+ state :under_supervision do
31
+ # TODO: move logic of Workflow::TasksController#update here
32
+ #validates_associated :result
33
+ end
34
+
35
+ event :follow_up do
36
+ transition [:under_supervision, :completed] => :assigned
37
+ end
38
+
39
+ event :complete do
40
+ # TODO: complete the story through observer
41
+ transition :under_supervision => :completed
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,41 @@
1
+ module StateMachines::Vacancy
2
+ def self.included(base)
3
+ base.extend ClassMethods
4
+
5
+ base.class_eval do
6
+ attr_accessor :current_user
7
+
8
+ const_set 'STATES', [:open, :recommended, :denied, :closed]
9
+ const_set 'EVENTS', [:accept_recommendation, :deny_recommendation, :close, :reopen]
10
+
11
+ state_machine :state, initial: :new do
12
+ event :recommend do
13
+ transition :new => :recommended
14
+ end
15
+
16
+ event :accept_recommendation do
17
+ transition :recommended => :open
18
+ end
19
+
20
+ event :deny_recommendation do
21
+ transition :recommended => :denied
22
+ end
23
+
24
+ event :do_open do
25
+ transition :new => :open
26
+ end
27
+
28
+ event :close do
29
+ transition :open => :closed
30
+ end
31
+
32
+ event :reopen do
33
+ transition [:denied, :closed] => :open
34
+ end
35
+ end
36
+ end
37
+ end
38
+
39
+ module ClassMethods
40
+ end
41
+ end
@@ -0,0 +1,82 @@
1
+ class Story
2
+ include Mongoid::Document
3
+ include Mongoid::Timestamps
4
+ include Mongoid::Slug
5
+
6
+ include Model::MongoDb::Customizable
7
+ include StateMachines::Story
8
+ include Model::MongoDb::Commentable
9
+
10
+ has_many :tasks, dependent: :destroy
11
+
12
+ # cached associations
13
+ has_many :results
14
+
15
+ accepts_nested_attributes_for :tasks, allow_destroy: true, reject_if: ->(t) { t['name'].blank? && t['text'].blank? }
16
+
17
+ field :project_id, type: Integer
18
+ field :offeror_id, type: Integer
19
+ field :name, type: String
20
+ field :text, type: String
21
+ field :state, type: String
22
+ field :users_without_tasks_ids, type: Array
23
+
24
+ slug :name
25
+
26
+ attr_accessible :project_id, :name, :text, :tasks_attributes
27
+
28
+ scope :active, where(state: 'active')
29
+
30
+ validates :project_id, presence: true
31
+ validates :offeror_id, presence: true
32
+ validates :name, presence: true, uniqueness: { scope: :project_id }
33
+ validates :text, presence: true
34
+
35
+ after_initialize :cache_associations
36
+ before_validation :cache_associations
37
+
38
+ PARENT_TYPES = ['project']
39
+
40
+ def self.for_user(user)
41
+ raise NotImplementedError
42
+ end
43
+
44
+ # belongs_to (SQL)
45
+ def offeror; offeror_id ? User.find(offeror_id) : nil; end
46
+ def offeror=(value); self.offeror_id = value.id; end
47
+
48
+ def project; project_id ? Project.find(project_id) : nil; end
49
+ def project=(value); self.project_id = value.id; end
50
+
51
+ def next_task_for_user(user)
52
+ return nil if (users_without_tasks_ids || []).include?(user.id)
53
+
54
+ task = tasks.assigned.where(user_id: user.id).first
55
+
56
+ return task if task
57
+
58
+ task = tasks.current.unassigned.where(:unassigned_user_ids.ne => user.id).first
59
+
60
+ if task
61
+ task.user_id = user.id
62
+
63
+ return task.errors.full_messages.join('<br/>') unless task.assign
64
+ else
65
+ self.users_without_tasks_ids ||= []
66
+ self.users_without_tasks_ids << user.id
67
+ save
68
+ end
69
+
70
+ task
71
+ end
72
+
73
+ private
74
+
75
+ def cache_associations
76
+ self.offeror_id = project.user_id if project_id.present? && (project rescue nil)
77
+ end
78
+
79
+ def cache_product_association
80
+ self.product_id = project.product_id if project_id.present? && (project rescue nil)
81
+ end
82
+ end
@@ -0,0 +1,85 @@
1
+ class Task
2
+ include Mongoid::Document
3
+ include Mongoid::Timestamps
4
+ include Mongoid::Slug
5
+ #include Mongoid::History::Trackable
6
+
7
+ include Model::MongoDb::Customizable
8
+ include Model::MongoDb::Commentable
9
+ include StateMachines::Task
10
+
11
+ belongs_to :story
12
+ belongs_to :result, dependent: :destroy
13
+
14
+ accepts_nested_attributes_for :result, allow_destroy: true
15
+
16
+ field :offeror_id, type: Integer
17
+ field :user_id, type: Integer
18
+ field :author_id, type: Integer
19
+ field :name, type: String
20
+ field :text, type: String
21
+ field :state, type: String
22
+ field :unassigned_user_ids, type: Array
23
+
24
+ slug :name
25
+
26
+ attr_accessible :story_id, :name, :text, :result_attributes
27
+
28
+ scope :current, where(state: 'new')
29
+ scope :unassigned, where(user_id: nil)
30
+ scope :assigned, ne(user_id: nil)
31
+ scope :complete, where(state: 'completed')
32
+ scope :incomplete, ne(state: 'completed')
33
+
34
+ validates :story_id, presence: true
35
+ validates :offeror_id, presence: true
36
+ validates :name, presence: true, uniqueness: { scope: :story_id }
37
+ validates :text, presence: true, if: ->(t) { t.class.name == 'Task' }
38
+ validate :reserved_words_exclusion
39
+
40
+ after_initialize :cache_associations
41
+ before_validation :cache_associations
42
+
43
+ #track_history on: [:user_id, :name, :text, :state]
44
+
45
+ PARENT_TYPES = ['story']
46
+
47
+ # belongs_to (SQL)
48
+ def offeror; offeror_id ? User.find(offeror_id) : nil; end
49
+ def offeror=(value); self.offeror_id = value.id; end
50
+
51
+ def user; user_id ? User.find(user_id) : nil; end
52
+ def user=(value); self.user_id = value.id; end
53
+
54
+ def author; author_id ? User.find(author_id) : nil; end
55
+ def author=(value); self.author_id = value.id; end
56
+
57
+ def result_class
58
+ if product_id.present?
59
+ "#{product.class.name}::Result".constantize rescue Result
60
+ else
61
+ Result
62
+ end
63
+ end
64
+
65
+ private
66
+
67
+ def reserved_words_exclusion
68
+ current_slug = to_param
69
+
70
+ if ['new', 'edit', 'next'].include?(current_slug)
71
+ message = I18n.t(
72
+ 'activerecord.errors.models.general.attributes.name.reserved_word_included'
73
+ )
74
+ errors[:name] << message unless errors[:name].include? message
75
+ end
76
+ end
77
+
78
+ def cache_associations
79
+ self.offeror_id = story.offeror_id if story_id.present? && (story rescue nil)
80
+ end
81
+
82
+ def cache_product_association
83
+ self.product_id = story.product_id if story_id.present? && (story rescue nil)
84
+ end
85
+ end
@@ -0,0 +1,95 @@
1
+ class User < ActiveRecord::Base
2
+ include ::Applicat::Mvc::Model::Resource::Base
3
+
4
+ belongs_to :main_role, class_name: 'Role'
5
+ belongs_to :profession
6
+
7
+ has_and_belongs_to_many :roles, join_table: 'users_roles'
8
+ has_and_belongs_to_many :areas
9
+ has_and_belongs_to_many :projects
10
+
11
+ has_many :offeror_vacancies, source: :offeror, class_name: 'Vacancy'
12
+ has_many :offeror_candidatures, source: :offeror, class_name: 'Candidature'
13
+ has_many :candidatures
14
+
15
+ accepts_nested_attributes_for :areas, allow_destroy: true
16
+
17
+ serialize :foreign_languages
18
+
19
+ validates :name, presence: true, uniqueness: true
20
+ validates :first_name, presence: true
21
+ validates :last_name, presence: true
22
+ validates :language, presence: true
23
+ validates :country, presence: true
24
+ validates :interface_language, presence: true
25
+
26
+ attr_accessible :name, :password, :password_confirmation, :text, :language, :first_name, :last_name,
27
+ :salutation, :marital_status, :family_status, :date_of_birth, :place_of_birth, :citizenship,
28
+ :email, :country, :language, :interface_language, :foreign_language_tokens, :profession_id,
29
+ :employment_relationship, :area_tokens,
30
+ # preferences
31
+ :main_role_id
32
+
33
+ # :timeoutable, :token_authenticatable, :lockable,
34
+ # :lock_strategy => :none, :unlock_strategy => :nones
35
+ devise :database_authenticatable, :registerable,# :confirmable,
36
+ :recoverable, :rememberable, :trackable, :validatable
37
+
38
+ extend FriendlyId
39
+
40
+ friendly_id :name, use: :slugged
41
+
42
+ after_create :set_main_role
43
+
44
+ PARENT_TYPES = ['area', 'project']
45
+
46
+ def self.languages(query = nil)
47
+ options = []
48
+
49
+ AVAILABLE_LANGUAGES.merge(OTHER_LANGUAGES).each do |locale, language|
50
+ next if query && !language.downcase.match(query.downcase)
51
+
52
+ if query
53
+ options << { id: locale, name: language }
54
+ else
55
+ options << [language, locale]
56
+ end
57
+ end
58
+
59
+ options
60
+ end
61
+
62
+ def languages
63
+ (foreign_languages || []) + [language]
64
+ end
65
+
66
+ def foreign_language_tokens=(tokens)
67
+ self.foreign_languages = tokens.split(',')
68
+ end
69
+
70
+ def foreign_language_tokens
71
+ options = []
72
+
73
+ User.languages.each do |language|
74
+ next unless (foreign_languages || []).include?(language.second)
75
+
76
+ options << { id: language.second, name: language.first }
77
+ end
78
+
79
+ options
80
+ end
81
+
82
+ def area_tokens=(tokens)
83
+ self.area_ids = Area.ids_from_tokens(tokens)
84
+ end
85
+
86
+ def area_tokens
87
+ areas
88
+ end
89
+
90
+ private
91
+
92
+ def set_main_role
93
+ self.update_attribute :main_role_id, Role.find_or_create_by_name('User').id
94
+ end
95
+ end