pshq_engine 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 (261) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +7 -0
  3. data/.travis.yml +3 -0
  4. data/Gemfile +4 -0
  5. data/README.md +39 -0
  6. data/Rakefile +1 -0
  7. data/app/models/.keep +0 -0
  8. data/app/models/ability.rb +76 -0
  9. data/app/models/alert.rb +56 -0
  10. data/app/models/asset.rb +485 -0
  11. data/app/models/asset_assignment.rb +13 -0
  12. data/app/models/asset_image.rb +9 -0
  13. data/app/models/asset_repair_request.rb +167 -0
  14. data/app/models/asset_scan.rb +87 -0
  15. data/app/models/asset_ticket.rb +3 -0
  16. data/app/models/cancellation.rb +64 -0
  17. data/app/models/candidate.rb +127 -0
  18. data/app/models/certification.rb +4 -0
  19. data/app/models/concerns/.keep +0 -0
  20. data/app/models/depreciation_setting.rb +10 -0
  21. data/app/models/dispatch.rb +3 -0
  22. data/app/models/employee.rb +22 -0
  23. data/app/models/feedback.rb +24 -0
  24. data/app/models/history_email.rb +221 -0
  25. data/app/models/importfile.rb +6 -0
  26. data/app/models/job.rb +37 -0
  27. data/app/models/jobs_users.rb +18 -0
  28. data/app/models/lateness.rb +35 -0
  29. data/app/models/location.rb +4 -0
  30. data/app/models/manufacturer.rb +4 -0
  31. data/app/models/member.rb +65 -0
  32. data/app/models/member_device.rb +4 -0
  33. data/app/models/message.rb +33 -0
  34. data/app/models/note.rb +20 -0
  35. data/app/models/notification.rb +73 -0
  36. data/app/models/notification_user.rb +4 -0
  37. data/app/models/o_auth/base.rb +27 -0
  38. data/app/models/o_auth/facebook.rb +21 -0
  39. data/app/models/o_auth/google.rb +18 -0
  40. data/app/models/organization.rb +189 -0
  41. data/app/models/plan.rb +4 -0
  42. data/app/models/project.rb +5 -0
  43. data/app/models/project_payment.rb +4 -0
  44. data/app/models/recurring_time_off.rb +4 -0
  45. data/app/models/response.rb +23 -0
  46. data/app/models/role.rb +22 -0
  47. data/app/models/schedule.rb +228 -0
  48. data/app/models/setting.rb +25 -0
  49. data/app/models/shift.rb +364 -0
  50. data/app/models/shift_off.rb +4 -0
  51. data/app/models/shift_trade.rb +43 -0
  52. data/app/models/subdomain.rb +5 -0
  53. data/app/models/swap.rb +82 -0
  54. data/app/models/task.rb +26 -0
  55. data/app/models/template.rb +59 -0
  56. data/app/models/template_asset.rb +3 -0
  57. data/app/models/timeoff.rb +101 -0
  58. data/app/models/token.rb +22 -0
  59. data/app/models/transaction.rb +2 -0
  60. data/app/models/unavailable.rb +37 -0
  61. data/app/models/user.rb +392 -0
  62. data/app/models/user_notification_setting.rb +178 -0
  63. data/app/models/user_vacation_info.rb +22 -0
  64. data/app/models/vacation.rb +24 -0
  65. data/app/models/vendor.rb +130 -0
  66. data/app/models/vendor_rating.rb +7 -0
  67. data/bin/console +14 -0
  68. data/bin/setup +7 -0
  69. data/db/migrate/20140211085026_devise_create_users.rb +58 -0
  70. data/db/migrate/20140211093822_rolify_create_roles.rb +19 -0
  71. data/db/migrate/20140211124352_create_subdomains.rb +9 -0
  72. data/db/migrate/20140211175737_devise_invitable_add_to_users.rb +24 -0
  73. data/db/migrate/20140222020040_create_schedules.rb +13 -0
  74. data/db/migrate/20140222020246_create_jobs.rb +11 -0
  75. data/db/migrate/20140222020348_create_shifts.rb +17 -0
  76. data/db/migrate/20140222020425_create_organizations.rb +19 -0
  77. data/db/migrate/20140226070901_create_plans.rb +11 -0
  78. data/db/migrate/20140302152936_create_feedbacks.rb +12 -0
  79. data/db/migrate/20140302153059_create_swaps.rb +16 -0
  80. data/db/migrate/20140302153215_create_timeoffs.rb +19 -0
  81. data/db/migrate/20140302153302_create_cancellations.rb +13 -0
  82. data/db/migrate/20140306014858_create_candidates.rb +15 -0
  83. data/db/migrate/20140314041018_create_shift_trades.rb +15 -0
  84. data/db/migrate/20140314041210_create_notes.rb +11 -0
  85. data/db/migrate/20140314041313_create_latenesses.rb +11 -0
  86. data/db/migrate/20140314041351_create_vacations.rb +11 -0
  87. data/db/migrate/20140314041440_create_user_vacation_infos.rb +11 -0
  88. data/db/migrate/20140318072438_create_jobs_users.rb +10 -0
  89. data/db/migrate/20140325151307_create_tasks.rb +16 -0
  90. data/db/migrate/20140406040247_create_mailboxer.mailboxer_engine.rb +66 -0
  91. data/db/migrate/20140406040248_add_conversation_optout.mailboxer_engine.rb +15 -0
  92. data/db/migrate/20141015085628_create_alerts.rb +14 -0
  93. data/db/migrate/20141023104634_add_disabled_to_users.rb +5 -0
  94. data/db/migrate/20141024094518_add_is_viewed_to_schedules.rb +5 -0
  95. data/db/migrate/20141027091531_add_customer_id_to_users.rb +5 -0
  96. data/db/migrate/20141029124637_create_unavailables.rb +11 -0
  97. data/db/migrate/20141029151702_create_certifications.rb +10 -0
  98. data/db/migrate/20141105091745_add_reminder_time_to_shifts.rb +5 -0
  99. data/db/migrate/20141106054916_create_certifications_users.rb +10 -0
  100. data/db/migrate/20141106100123_add_birth_date_to_users.rb +5 -0
  101. data/db/migrate/20141106134815_add_allow_rolling_v_hrs_to_organizations.rb +5 -0
  102. data/db/migrate/20141107155319_create_recurring_time_offs.rb +12 -0
  103. data/db/migrate/20141111084845_add_termination_date_to_users.rb +5 -0
  104. data/db/migrate/20141111103759_add_requested_weekly_hours_to_users.rb +5 -0
  105. data/db/migrate/20141113094547_add_api_token_to_users.rb +5 -0
  106. data/db/migrate/20150105143729_create_templates.rb +9 -0
  107. data/db/migrate/20150105164236_add_coloumn_is_template.rb +5 -0
  108. data/db/migrate/20150106121306_add_org_id.rb +5 -0
  109. data/db/migrate/20150126070904_add_job_id_to_shifts.rb +6 -0
  110. data/db/migrate/20150203112955_add_time_zone_to_org.rb +5 -0
  111. data/db/migrate/20150204160711_add_show_owner_to_org.rb +5 -0
  112. data/db/migrate/20150210165627_add_training_hours_to_shift.rb +9 -0
  113. data/db/migrate/20150217131509_add_total_hours_to_schedules.rb +5 -0
  114. data/db/migrate/20150218094709_add_show_disable_users.rb +5 -0
  115. data/db/migrate/20150225134050_add_notes_to_cancellation.rb +9 -0
  116. data/db/migrate/20150226125524_add_unexcused_absence_note_to_cancellation.rb +9 -0
  117. data/db/migrate/20150226125811_add_cancel_shift_to_shifts.rb +9 -0
  118. data/db/migrate/20150302100542_add_picture_to_user.rb +9 -0
  119. data/db/migrate/20150304082219_add_priorty_to_user.rb +9 -0
  120. data/db/migrate/20150304094605_add_time_format_to_organization.rb +8 -0
  121. data/db/migrate/20150304142621_create_shift_offs.rb +15 -0
  122. data/db/migrate/20150306120726_add_shiftoff_to_shifts.rb +9 -0
  123. data/db/migrate/20150310103643_add_email_and_number_to_user.rb +11 -0
  124. data/db/migrate/20150311110055_add_one_sided_to_candidate.rb +9 -0
  125. data/db/migrate/20150318083934_add_notes_to_shift_trade.rb +9 -0
  126. data/db/migrate/20150408180855_add_column_status_to_unavailability.rb +8 -0
  127. data/db/migrate/20150409140324_create_assets.rb +35 -0
  128. data/db/migrate/20150409142753_create_vendors.rb +14 -0
  129. data/db/migrate/20150409144023_create_employees.rb +13 -0
  130. data/db/migrate/20150409144751_create_assign_assets.rb +16 -0
  131. data/db/migrate/20150409150449_create_asset_repair_requests.rb +19 -0
  132. data/db/migrate/20150409151023_create_dispatches.rb +13 -0
  133. data/db/migrate/20150409151329_create_vendor_ratings.rb +11 -0
  134. data/db/migrate/20150409151546_create_template_assets.rb +11 -0
  135. data/db/migrate/20150413101913_create_index_organization.rb +7 -0
  136. data/db/migrate/20150414153330_change_vendors.rb +16 -0
  137. data/db/migrate/20150420112003_add_name_to_users.rb +5 -0
  138. data/db/migrate/20150421074542_add_comment_to_ratings.rb +5 -0
  139. data/db/migrate/20150421131331_add_retire_column_to_assets.rb +5 -0
  140. data/db/migrate/20150422135600_add_attachment_avatar_to_assets.rb +11 -0
  141. data/db/migrate/20150422143242_create_importfiles.rb +8 -0
  142. data/db/migrate/20150422143301_add_attachment_avatar_to_importfiles.rb +11 -0
  143. data/db/migrate/20150423080234_change_retire_column.rb +5 -0
  144. data/db/migrate/20150423170953_add_attachment_avatar_to_vendors.rb +11 -0
  145. data/db/migrate/20150423225459_add_lockable.rb +7 -0
  146. data/db/migrate/20150427171842_create_asset_scans.rb +15 -0
  147. data/db/migrate/20150429211309_add_attachment_logo_to_organizations.rb +11 -0
  148. data/db/migrate/20150430074555_change_assets_table.rb +8 -0
  149. data/db/migrate/20150430235920_add_unique_email_index_to_users.rb +5 -0
  150. data/db/migrate/20150505104834_add_columntouser.rb +8 -0
  151. data/db/migrate/20150505140926_add_maintenance_cost_to_assets.rb +6 -0
  152. data/db/migrate/20150505142413_create_asset_images.rb +8 -0
  153. data/db/migrate/20150505152604_create_pg_search_documents.rb +17 -0
  154. data/db/migrate/20150506090012_change_employee.rb +12 -0
  155. data/db/migrate/20150506110441_add_status_to_asset_repair_requests.rb +6 -0
  156. data/db/migrate/20150507080738_change_phone_in_employees.rb +6 -0
  157. data/db/migrate/20150507101306_create_manufacturers.rb +12 -0
  158. data/db/migrate/20150507101446_remove.rb +9 -0
  159. data/db/migrate/20150507102211_add_index_manufacturer.rb +5 -0
  160. data/db/migrate/20150507104605_add_website_manufacturer.rb +5 -0
  161. data/db/migrate/20150507115535_change_refrence_manucaturer.rb +6 -0
  162. data/db/migrate/20150507150848_create_notifications.rb +9 -0
  163. data/db/migrate/20150507150855_create_notification_users.rb +10 -0
  164. data/db/migrate/20150508094912_add_landline_to_organization.rb +5 -0
  165. data/db/migrate/20150508143536_add_source_to_notifications.rb +7 -0
  166. data/db/migrate/20150508145048_add_postal_to_profile.rb +5 -0
  167. data/db/migrate/20150508162219_add_summary_to_notifications.rb +5 -0
  168. data/db/migrate/20150509220624_remove_responded_from_notifications.rb +5 -0
  169. data/db/migrate/20150509220625_add_responded_to_notifications.rb +5 -0
  170. data/db/migrate/20150509225608_change_columns_asset_repair_requests.rb +11 -0
  171. data/db/migrate/20150511105420_remove_avatar_asset.rb +6 -0
  172. data/db/migrate/20150514105700_add_unique_asset_id_to_asset.rb +5 -0
  173. data/db/migrate/20150515110042_add_deleted_at_in_assets.rb +6 -0
  174. data/db/migrate/20150515111410_add_deleted_at_vendors.rb +6 -0
  175. data/db/migrate/20150515113054_add_deleted_at_in_employee.rb +6 -0
  176. data/db/migrate/20150515142228_create_locations.rb +16 -0
  177. data/db/migrate/20150515142242_add_locations_to_assets.rb +5 -0
  178. data/db/migrate/20150515142536_add_organization_to_locations.rb +5 -0
  179. data/db/migrate/20150518123010_change_assign_asset.rb +9 -0
  180. data/db/migrate/20150518140153_add_asset_id_in_asset_assign.rb +5 -0
  181. data/db/migrate/20150518144758_rename_assign_assets.rb +8 -0
  182. data/db/migrate/20150518145248_rename_asset_assignment.rb +8 -0
  183. data/db/migrate/20150519140425_change_empid_to_string.rb +6 -0
  184. data/db/migrate/20150521085132_change_uique_asset_id_to_string.rb +6 -0
  185. data/db/migrate/20150525095045_add_status_to_organizations.rb +5 -0
  186. data/db/migrate/20150525123202_create_transactions.rb +20 -0
  187. data/db/migrate/20150526124755_create_settings.rb +16 -0
  188. data/db/migrate/20150603163451_add_cost_comment_collected_by_to_asset_repair_request.rb +7 -0
  189. data/db/migrate/20150605144111_collected.rb +5 -0
  190. data/db/migrate/20150609111725_add_column_notification.rb +5 -0
  191. data/db/migrate/20150609170014_create_user_notification_settings.rb +13 -0
  192. data/db/migrate/20150609175555_add_city_to_locations.rb +4 -0
  193. data/db/migrate/20150612190052_addcity.rb +5 -0
  194. data/db/migrate/20150614215015_create_members.rb +27 -0
  195. data/db/migrate/20150616070816_add_organization_to_schedules.rb +9 -0
  196. data/db/migrate/20150616114344_change_timestape_to_date.rb +4 -0
  197. data/db/migrate/20150619085555_add_index_repair_scan_to_repair.rb +6 -0
  198. data/db/migrate/20150623120915_create_depreciation_settings.rb +9 -0
  199. data/db/migrate/20150624060402_add_depriciation_ref_to_assets.rb +5 -0
  200. data/db/migrate/20150624085501_add_organization_ref_dep.rb +5 -0
  201. data/db/migrate/20150624114339_add_user_to_vacation_info.rb +9 -0
  202. data/db/migrate/20150624131422_change_dep_seeting.rb +6 -0
  203. data/db/migrate/20150625090838_add_dep_cost_col_in_assets.rb +5 -0
  204. data/db/migrate/20150626123545_add_vendor_id_to_asset.rb +5 -0
  205. data/db/migrate/20150629095216_add_depreciated_cost_asset.rb +5 -0
  206. data/db/migrate/20150629124325_add_allow_vendor_additon_to_setings.rb +7 -0
  207. data/db/migrate/20150630080925_add_approve_to_vendor.rb +5 -0
  208. data/db/migrate/20150630112252_add_referrenc_dereciation_to_asset.rb +5 -0
  209. data/db/migrate/20150630124838_add_ref_dep_organization.rb +5 -0
  210. data/db/migrate/20150707102850_add_column_sittings_to_delete_ticket.rb +6 -0
  211. data/db/migrate/20150710150314_add_org_ref_to_subdomain.rb +5 -0
  212. data/db/migrate/20150713204553_add_hire_dateto_member.rb +9 -0
  213. data/db/migrate/20150714004440_add_organization_to_notes.rb +9 -0
  214. data/db/migrate/20150714100444_add_time_format_to_member.rb +9 -0
  215. data/db/migrate/20150714202050_create_asset_tickets.rb +11 -0
  216. data/db/migrate/20150722151752_add_invitation_counts_to_user.rb +10 -0
  217. data/db/migrate/20150723141352_add_invitation_created_at_to_member.rb +10 -0
  218. data/db/migrate/20150724105130_create_projects.rb +8 -0
  219. data/db/migrate/20150724105257_create_project_payments.rb +13 -0
  220. data/db/migrate/20150724220844_add_user_index_to_asset.rb +6 -0
  221. data/db/migrate/20150727085046_add_projects_to_organization.rb +11 -0
  222. data/db/migrate/20150727122551_add_coloumn_to_vendors.rb +5 -0
  223. data/db/migrate/20150727211029_add_column_code_to_asset.rb +5 -0
  224. data/db/migrate/20150728101649_add_disabled_to_member.rb +9 -0
  225. data/db/migrate/20150731095354_add_column_repair_date_to_asset.rb +6 -0
  226. data/db/migrate/20150731104152_add_column_repair_reminder_setting.rb +5 -0
  227. data/db/migrate/20150806085559_create_member_devices.rb +10 -0
  228. data/db/migrate/20150807133155_add_view_to_alert.rb +9 -0
  229. data/db/migrate/20150808151840_app_col_in_member_device.rb +5 -0
  230. data/db/migrate/20150808180234_add_deleted_at_toalerts.rb +7 -0
  231. data/db/migrate/20150810110136_add_address_in_4_feilds_vendor.rb +12 -0
  232. data/db/migrate/20150810172933_change_column_type_in_vendors.rb +6 -0
  233. data/db/migrate/20150811061019_change_column_in_vendors.rb +5 -0
  234. data/db/migrate/20150811133002_change_shift_off_time.rb +5 -0
  235. data/db/migrate/20150811135657_change_column_type_timestamp_to_date.rb +7 -0
  236. data/db/migrate/20150818131207_create_history_emails.rb +10 -0
  237. data/db/migrate/20150820115042_change_schedule_total_hours.rb +6 -0
  238. data/db/migrate/20150820120309_add_column_email_remove.rb +5 -0
  239. data/db/migrate/20150820121702_add_column_email_organization.rb +5 -0
  240. data/db/migrate/20150824085019_add_column_asset_purchase_vendor.rb +5 -0
  241. data/db/migrate/20150826122944_add_column_exipry_notification.rb +5 -0
  242. data/db/migrate/20150827113937_create_members_roles.rb +9 -0
  243. data/db/migrate/20150828145913_add_locable_to_member.rb +7 -0
  244. data/db/migrate/20150903155708_add_vendor_feilds_to_user.rb +8 -0
  245. data/db/migrate/20150903200953_add_shift_to_candidate.rb +9 -0
  246. data/db/migrate/20150904082434_add_one_sided_to_trade_shift.rb +9 -0
  247. data/db/migrate/20150904134529_add_column_in_setting_user_dispatch.rb +5 -0
  248. data/db/migrate/20150907082501_add_website_for_vendor.rb +6 -0
  249. data/db/migrate/20150907141100_add_dollar_limit_to_user.rb +5 -0
  250. data/db/migrate/20150907193030_add_estimate_in_repair.rb +8 -0
  251. data/db/migrate/20150908123735_add_vendor_aproval_in_repair.rb +10 -0
  252. data/db/migrate/20150909112005_add_column_amount_into_plan.rb +5 -0
  253. data/db/migrate/20150916131512_add_plan_name_to_project_payment.rb +9 -0
  254. data/db/schema.rb +909 -0
  255. data/db/seeds.rb +23 -0
  256. data/lib/assets/.keep +0 -0
  257. data/lib/pshq_engine/version.rb +3 -0
  258. data/lib/pshq_engine.rb +5 -0
  259. data/lib/tasks/.keep +0 -0
  260. data/pshq_engine.gemspec +26 -0
  261. metadata +330 -0
@@ -0,0 +1,364 @@
1
+ # == Schema Information
2
+ #
3
+ # Table name: shifts
4
+ #
5
+ # id :integer not null, primary key
6
+ # day_of_week :integer
7
+ # start_time :time
8
+ # end_time :time
9
+ # hours :time
10
+ # schedule_id :integer
11
+ # created_at :datetime
12
+ # updated_at :datetime
13
+ # due_date :date
14
+ # absence :boolean default(FALSE)
15
+ #
16
+
17
+ class Shift < ActiveRecord::Base
18
+
19
+ belongs_to :schedule
20
+ belongs_to :job
21
+ belongs_to :shift_offs
22
+
23
+ has_one :swap, :dependent => :destroy
24
+ has_one :cancellation, :dependent => :destroy
25
+ has_one :lateness, :dependent => :destroy
26
+ has_one :unavailable, :dependent => :destroy
27
+
28
+ #validate :should_real_time
29
+ validate :should_have_no_time_off
30
+ #validate :detect_overlap
31
+ #validates_presence_of :schedule
32
+ validates_presence_of :job
33
+ # validates_inclusion_of :day_of_week, :in => 0..6
34
+ # validates_uniqueness_of :day_of_week, :scope => :schedule
35
+ #validates_uniqueness_of :due_date, :scope => :schedule
36
+ validates_time :start_time
37
+ validates_time :end_time, :after => :start_time
38
+ validates_date :due_date
39
+
40
+ after_create :calculate_schedule_hours
41
+ after_save :calculate_schedule_hours
42
+ after_destroy { |record| check_schedule_for_deletion(record.schedule_id) }
43
+
44
+ def job_name
45
+ self.job.name
46
+ end
47
+
48
+ def user_name
49
+ self.schedule.user.name
50
+ end
51
+
52
+ def get_week_hours(user)
53
+ if user and user != 0
54
+ user = User.find(user)
55
+ user.shifts.where("due_date >= ? AND due_date <= ?",self.due_date.beginning_of_week,self.due_date.end_of_week ).sum(:hours).to_i
56
+ else
57
+ self.schedule.shifts.where("due_date >= ? AND due_date <= ?",self.due_date.beginning_of_week,self.due_date.end_of_week ).sum(:hours).to_i
58
+ end
59
+ end
60
+
61
+ def if_swap_approved(user)
62
+ if user and user != 0
63
+ swapped = Candidate.find_by_alert_type_id(self.id)
64
+ return (get_week_hours(user) + swapped.swap.shift.hours.strftime('%H').to_i)
65
+ else
66
+ swapped = Candidate.find_by_alert_type_id(self.id)
67
+ return (get_week_hours(0) + swapped.swap.shift.hours.strftime('%H').to_i)
68
+ end
69
+ end
70
+
71
+ def formatted_due_date
72
+ "#{due_date.strftime('%m')}/#{due_date.strftime('%d')}/#{due_date.strftime('%Y')}"
73
+ end
74
+ def status
75
+ state = 'normal'
76
+ if swap && swap.pending?
77
+ state = 'swap_pending'
78
+ end
79
+
80
+ if cancellation && cancellation.pending?
81
+ state = 'cancellation_pending'
82
+ end
83
+
84
+ state
85
+ end
86
+
87
+ def shift_detail
88
+ "AS #{self.job_name} from #{self.start_time.strftime('%H:%M')} to #{self.end_time.strftime('%H:%M')} on #{self.formatted_due_date}"
89
+ end
90
+
91
+ def published?
92
+ self.schedule.published?
93
+ end
94
+
95
+ def is_timeoff?
96
+ timeoff = Timeoff.where(:user_id => self.schedule.user_id, :off_date=>self.due_date,:status=>"approved")
97
+ timeoff.size > 0
98
+ end
99
+
100
+ def timeoff_reason
101
+ timeoff = self.schedule.user.timeoffs.where(:off_date => self.due_date,:status=>"approved").first
102
+ "The Reason : #{timeoff.reason}, All day : #{timeoff.all_day}, Vacation : #{timeoff.vacation} " if timeoff
103
+ end
104
+
105
+ def is_cancelled?
106
+ cancellation = Cancellation.where('shift_id = ? AND (status = ? OR status = ?)',self.id,"approved excused","approved unexcused")
107
+ cancellation.size > 0
108
+ end
109
+
110
+ def is_swapped?
111
+ swap = Swap.where(:shift_id=>self.id,:status=>"approved")
112
+ swap.size > 0
113
+ end
114
+
115
+ def swap_shift dest_sch, org, date
116
+ curr = self.schedule
117
+ dates = Date.parse(dest_sch[:due_date])
118
+ if dest_sch[:schedule_id].present?
119
+ new_schedule = Schedule.find_by_id(dest_sch[:schedule_id])
120
+ else
121
+ new_schedule = Schedule.new(user_id: dest_sch[:employee_id], organization_id: org.id,
122
+ total_hours: '0:0', start_date: curr.start_date, end_date: curr.end_date)
123
+ unless new_schedule.save!
124
+ return new_schedule
125
+ end
126
+ end
127
+ self.update_attributes!(schedule_id: new_schedule.id, day_of_week: dest_sch[:day_of_week], due_date: dates)
128
+ curr.destroy! if curr.shifts.count == 0
129
+ return self
130
+ end
131
+
132
+ def has_issue?
133
+ if swp = swap and swp.status == "pending"
134
+ return { "status"=> true, "type"=> "swap pending" }
135
+ elsif unavail = unavailable and unavail.status == "pending"
136
+ return { "status"=> true, "type"=> "unavailable pending" }
137
+ elsif cancel = cancellation and cancel.status == "pending"
138
+ return { "status"=> true, "type"=> "cancel pending" }
139
+ elsif Timeoff.where('user_id = ? AND off_date = ? AND status = ?',self.schedule.user_id, self.due_date, "pending").count > 0
140
+ return { "status"=> true, "type"=> "timeoff pending" }
141
+ elsif late = lateness
142
+ return { "status"=> true, "type"=> "lateness" }
143
+ end
144
+ return { "status"=> false }
145
+ end
146
+
147
+ def can_edit?
148
+ edit_possible = true
149
+ if self.swap && swap.approved?
150
+ edit_possible = true
151
+ elsif self.cancellation && self.cancellation.approved?
152
+ edit_possible = true
153
+ end
154
+ edit_possible
155
+ end
156
+
157
+ def avail?
158
+ self.published? && self.can_edit?
159
+ end
160
+
161
+ #private
162
+ #def detect_overlap
163
+ # if self.schedule_id
164
+ # schedule = Schedule.find(self.schedule_id)
165
+ # if schedule
166
+ # overlap = schedule.user.shifts.where(:due_date => self.due_date).first
167
+ # if overlap && overlap.id != self.id
168
+ # errors.add(:due_date, "can't create because already user has shift #{self.due_date} ")
169
+ # end
170
+ # end
171
+ # end
172
+ #end
173
+
174
+ #private
175
+ #def should_real_time
176
+ # if self.start_time > self.end_time
177
+ # errors.add(:start_time, "can't be in later than end time")
178
+ # end
179
+ #end
180
+
181
+ private
182
+ def should_have_no_time_off
183
+ if self.schedule_id
184
+ schedule = Schedule.find(self.schedule_id)
185
+ if schedule
186
+ timeoff = schedule.user.timeoffs.where(:off_date => self.due_date).first
187
+ if timeoff && timeoff.approved?
188
+ if timeoff.all_day_absence?
189
+ errors.add(:due_date, "can't create because already user requested time off on #{self.due_date} all day.")
190
+ elsif timeoff.interfere?(self.start_time, self.end_time)
191
+ errors.add(:due_date, "can't create because already user requested time off on #{self.due_date} #{self.start_time} #{self.end_time}")
192
+ end
193
+ end
194
+ end
195
+ end
196
+ end
197
+
198
+ def check_schedule_for_deletion schedule_id
199
+ schedule = Schedule.find_by_id(schedule_id)
200
+ if schedule and schedule.shifts.count == 0
201
+ schedule.destroy
202
+ else
203
+ schedule.calculate_total_hours
204
+ end
205
+ end
206
+
207
+ def self.create_with_json(schedule, data,changed)
208
+ data.each do |shift|
209
+ if shift["hours"] == ""
210
+ shift["hours"] = "0:0"
211
+ end
212
+ if shift["training_hours"] == ""
213
+ shift["training_hours"] = "0:0"
214
+ end
215
+ if shift["id"].nil?
216
+ # create new one
217
+ new_shift = schedule.shifts.new(:start_time => shift["start_time"],
218
+ :end_time => shift["end_time"],
219
+ :day_of_week => shift["day_of_week"],
220
+ :hours => shift["hours"],
221
+ :training_hours => shift["training_hours"],
222
+ :due_date => shift["due_date"],
223
+ :job_id => shift["job_id"],
224
+ :shift_off_id => shift["shift_off_id"]
225
+ )
226
+
227
+ unless new_shift.save
228
+ return new_shift.errors
229
+ end
230
+ else
231
+ # modify existing one
232
+ ext_shift = Shift.find(shift["id"])
233
+ if ext_shift
234
+ ext_shift.start_time = shift["start_time"]
235
+ ext_shift.end_time = shift["end_time"]
236
+ ext_shift.job_id = shift["job_id"]
237
+ ext_shift.day_of_week = shift["day_of_week"]
238
+ ext_shift.hours = shift["hours"]
239
+ ext_shift.due_date = shift["due_date"]
240
+ ext_shift.job_id = shift["job_id"]
241
+ ext_shift.shift_off_id = shift["shift_off_id"]
242
+ shift_changed = ext_shift.changed?
243
+ result = ext_shift.save
244
+ if shift_changed
245
+ changed = true
246
+ end
247
+ unless result
248
+ return ext_shift.errors
249
+ end
250
+ end
251
+ end
252
+ end
253
+ # if changed and schedule.publish?
254
+ # schedule.notify_employee
255
+ # end
256
+ true
257
+ end
258
+
259
+
260
+ def self.week_shifts schedule, user, org, date
261
+ w_shifts = []
262
+ shifts = schedule.try(:shifts)
263
+ daily_shifts = shifts.sort_by(&:start_time).group_by(&:day_of_week) if shifts.present?
264
+ weekdaysrange(org.m_to_s).each do |i|
265
+ if daily_shifts.present? && daily_shifts[i].present?
266
+ w_shifts << self.format_shift(schedule, daily_shifts[i], i)
267
+ else
268
+ w_shifts << self.fill_shift(schedule, user, i, org, date)
269
+ end
270
+ end
271
+
272
+ w_shifts
273
+ end
274
+
275
+ def self.day(day, m_to_s)
276
+ days = m_to_s ? ["Mon","Tue","Wed","Thur","Fri","Sat", "Sun"] : ["Sun", "Mon","Tue","Wed","Thur","Fri","Sat"];
277
+ days[day]
278
+ end
279
+
280
+ def self.days(m_to_s, date)
281
+ days = []
282
+ currdate = Date.parse(date).at_beginning_of_week
283
+ currdate = m_to_s ? currdate - 1 : currdate - 2 ;
284
+ (0..6).each do |day_of_week|
285
+ currdate = currdate + 1
286
+ obj = {'month'=> currdate.month,'date'=> currdate.day,'year'=> currdate.year, 'day'=> day(day_of_week, m_to_s)}
287
+ days.push(obj)
288
+ end
289
+ days
290
+ end
291
+
292
+ def self.get_day m_to_s, day_of_week, date
293
+ dates = Date.parse(date).at_beginning_of_week + day_of_week
294
+ dates = dates - 1 if m_to_s
295
+ dates
296
+ end
297
+
298
+ def self.weekdaysrange(m_to_s)
299
+ m_to_s ? (1..7) : (0..6)
300
+ end
301
+
302
+ def self.format_shift schedule, shifts, day
303
+ d_shifts = []
304
+ shifts.each do |shift|
305
+ dshift = {}
306
+ job = shift.job
307
+ dshift["id"] = shift.id
308
+ dshift["job_id"] = job.id
309
+ dshift["job_name"] = job.name
310
+ dshift["start_time"] = shift.try(:start_time).try(:strftime, '%I:%M%P') || 0.0
311
+ dshift["end_time"] = shift.try(:end_time).try(:strftime,'%I:%M%P') || 0.0
312
+ dshift["hours"] = shift.try(:hours).try(:strftime,'%H:%M') || 0.0
313
+ dshift["training_hours"] = shift.try(:training_hours).try(:strftime,'%H:%M') || 0.0
314
+ dshift["shift_off_id"] = shift.shift_off_id
315
+ dshift["due_date"] = shift.due_date
316
+ dshift["is_timeoff"] = shift.is_timeoff?
317
+ dshift["is_cancelled"] = shift.is_cancelled?
318
+ dshift["cancel_reason"] = shift.cancellation.try(:reason)
319
+ dshift["timeoff_reason"] = shift.timeoff_reason
320
+ dshift["is_swapped"] = shift.is_swapped?
321
+ dshift["color"] = job.color
322
+ dshift["has_issue"] = shift.has_issue?
323
+ dshift["day_of_week"] = day%7
324
+ dshift["schedule_id"] = schedule.try(:id)
325
+ dshift["employee_id"] = schedule.user_id
326
+ dshift["shift_off"] = ShiftOff.where(:id => shift.shift_off_id).first.name if shift.try(:shift_off_id)
327
+ d_shifts << dshift
328
+ end
329
+ d_shifts
330
+ end
331
+
332
+ def self.fill_shift schedule, emp, day, org, date
333
+ shift = {}
334
+ shift["id"] = nil
335
+ shift["hours"] = ""
336
+ shift["start_time"] = ""
337
+ shift["end_time"] = ""
338
+ shift["shift_off_id"] = nil
339
+ shift["day_of_week"] = day
340
+ shift["employee_id"] = emp.id
341
+ shift["due_date"] = get_day(org.m_to_s, day, date)
342
+ shift["training_hours"] = ""
343
+ shift["job_id"] = nil
344
+ shift["schedule_id"] = schedule.try(:id)
345
+ return [shift]
346
+ end
347
+
348
+ def self.daily schedules, date
349
+ filtered_shifts = []
350
+ shifts = self.where(:schedule_id => schedules, :due_date => date)
351
+ shifts.each do |shift|
352
+ user = shift.schedule.user
353
+ filtered_shifts << shift.attributes.merge(:user_id => user.id, :user_name => user.name)
354
+ end
355
+ filtered_shifts
356
+ end
357
+
358
+ def calculate_schedule_hours
359
+ if self.schedule
360
+ self.schedule.calculate_total_hours
361
+ end
362
+ end
363
+
364
+ end
@@ -0,0 +1,4 @@
1
+ class ShiftOff < ActiveRecord::Base
2
+ belongs_to :organization
3
+ has_many :shifts
4
+ end
@@ -0,0 +1,43 @@
1
+ # == Schema Information
2
+ #
3
+ # Table name: shift_trades
4
+ #
5
+ # id :integer not null, primary key
6
+ # status :string(255) default("initial")
7
+ # candidate_id :integer
8
+ # shift_id :integer
9
+ # created_at :datetime
10
+ # updated_at :datetime
11
+ #
12
+
13
+ class ShiftTrade < ActiveRecord::Base
14
+
15
+ belongs_to :candidate
16
+ belongs_to :shift
17
+ belongs_to :organization
18
+ belongs_to :user
19
+ validates_presence_of :candidate
20
+
21
+ def affirm
22
+ self.status = 'affirmative'
23
+ save
24
+ end
25
+
26
+ def negate
27
+ self.status = 'negative'
28
+ save
29
+ end
30
+
31
+ def ignore
32
+ self.status = 'ignored'
33
+ save
34
+ end
35
+
36
+ def confirm()
37
+ self.status = 'confirmed'
38
+ save
39
+
40
+ self.candidate.confirm(self.id)
41
+ end
42
+
43
+ end
@@ -0,0 +1,5 @@
1
+ class Subdomain < ActiveRecord::Base
2
+ belongs_to :organization
3
+ validates_uniqueness_of :name
4
+ validates_uniqueness_of :name, :case_sensitive => false
5
+ end
@@ -0,0 +1,82 @@
1
+ # == Schema Information
2
+ #
3
+ # Table name: swaps
4
+ #
5
+ # id :integer not null, primary key
6
+ # shift_id :integer
7
+ # reason :string(255)
8
+ # status :string(255) default("pending")
9
+ # in_trash :boolean default(FALSE)
10
+ # viewed :boolean default(FALSE)
11
+ # created_at :datetime
12
+ # updated_at :datetime
13
+ # alert :boolean default(FALSE)
14
+ # approved_date :datetime
15
+ # approved_by :integer
16
+ #
17
+
18
+ class Swap < ActiveRecord::Base
19
+
20
+ belongs_to :shift
21
+
22
+ has_many :candidates, :dependent => :destroy
23
+ has_many :shift_trades, :through => :candidates
24
+
25
+ validates_presence_of :shift
26
+ validates_uniqueness_of :shift_id
27
+
28
+ def notify
29
+ if alert
30
+ employees = shift.schedule.user.organization.get_employees
31
+ employees.each do |candidate|
32
+ candidate.notify_alert(self)
33
+ end
34
+ end
35
+ end
36
+ def shift_detail
37
+ "AS #{shift.job_name} from #{shift.start_time.strftime('%H:%M')} to #{shift.end_time.strftime('%H:%M')} on #{shift.formatted_due_date}"
38
+
39
+ end
40
+ def pending?
41
+ self.status == 'pending'
42
+ end
43
+
44
+ def approved?
45
+ self.status == 'approved'
46
+ end
47
+
48
+ def user_name
49
+ self.shift.schedule.user.name
50
+ end
51
+
52
+
53
+ def get_shift
54
+ @swap = Swap.find_by_id(self.alert_type_id)
55
+ if !@swap.nil?
56
+ @swap.shift
57
+ end
58
+ end
59
+
60
+ def shift_hours
61
+ self.shift.hours.strftime('%H')
62
+ end
63
+
64
+ def due_date
65
+ self.shift.due_date
66
+ end
67
+
68
+ def approve
69
+ #self.approved_by = manager.id
70
+ #self.approved_date = Time.zone.now
71
+ self.status = 'approved'
72
+ save
73
+ end
74
+
75
+ def cancel
76
+ #self.approved_by = manager.id
77
+ #self.approved_date = Time.zone.now
78
+ self.status = 'cancelled'
79
+ save
80
+ end
81
+
82
+ end
@@ -0,0 +1,26 @@
1
+ # == Schema Information
2
+ #
3
+ # Table name: tasks
4
+ #
5
+ # id :integer not null, primary key
6
+ # organization_id :integer
7
+ # user_id :integer
8
+ # task_name :string(255)
9
+ # duty_time :time
10
+ # accept :boolean default(FALSE)
11
+ # done :boolean default(FALSE)
12
+ # duty_date :date
13
+ # created_at :datetime
14
+ # updated_at :datetime
15
+ #
16
+
17
+ class Task < ActiveRecord::Base
18
+
19
+ belongs_to :organization
20
+ belongs_to :user
21
+
22
+ # validates_time :duty_time
23
+ validates_date :duty_date
24
+ validates_presence_of :task_name
25
+
26
+ end
@@ -0,0 +1,59 @@
1
+ class Template < ActiveRecord::Base
2
+ has_many :template_assets
3
+ belongs_to :organization
4
+ has_many :schedules
5
+
6
+ # function for MT2W
7
+ def add_schedules schedules
8
+ Schedule.where(:id => schedules).each do |schedule|
9
+ sch = Schedule.new(schedule.attributes.merge({:id => nil, :template_id => self.id}))
10
+ if sch.save!(:validate => false)
11
+ schedule.shifts.each do |shf|
12
+ shift = Shift.new(shf.attributes.merge({:id => nil, :schedule_id => sch.id}))
13
+ shift.save!(:validate => false)
14
+ end
15
+ end
16
+ end
17
+ end
18
+
19
+ def add_schedules_from_date date, org
20
+ Schedule.where(:organization_id => org. id).not_template.week_schedule_by_date(date).each do |schedule|
21
+ sch = Schedule.new(schedule.attributes.merge({:id => nil, :template_id => self.id}))
22
+ if sch.save!(:validate => false)
23
+ schedule.shifts.each do |shf|
24
+ shift = Shift.new(shf.attributes.merge({:id => nil, :schedule_id => sch.id}))
25
+ shift.save!(:validate => false)
26
+ end
27
+ end
28
+ end
29
+ end
30
+
31
+ def load_schedules date, m_to_s
32
+ date = Date.parse date
33
+ if m_to_s
34
+ start_day = date - date.wday + 1.day
35
+ end_day = date - date.wday + 7.day
36
+ else
37
+ start_day = date - date.wday + 0.day
38
+ end_day = date - date.wday + 6.day
39
+ end
40
+
41
+ curr_schedules = Schedule.week_schedule_by_date(date).not_template
42
+ curr_schedules.delete_all if curr_schedules.length > 0
43
+ self.schedules.includes(:shifts).each do |schedule|
44
+ sch_attr = schedule.attributes.merge({ :id => nil, :template_id => nil, :start_date => start_day,
45
+ :end_date => end_day, :publish => false })
46
+ sch = Schedule.new(sch_attr)
47
+ schedule.shifts.each do |shift|
48
+ attributes = shift.attributes.merge({id: nil}).except("schedule_id")
49
+ attributes['due_date'] = start_day + attributes['day_of_week']
50
+ attributes['due_date'] = attributes['due_date'] - 1 if m_to_s
51
+ sch.shifts.build(attributes)
52
+ end
53
+ sch.save!(:validate => false)
54
+ end
55
+
56
+ return true
57
+ end
58
+
59
+ end
@@ -0,0 +1,3 @@
1
+ class TemplateAsset < ActiveRecord::Base
2
+ belongs_to :asset
3
+ end
@@ -0,0 +1,101 @@
1
+ # == Schema Information
2
+ #
3
+ # Table name: timeoffs
4
+ #
5
+ # id :integer not null, primary key
6
+ # day_of_week :integer
7
+ # reason :string(255)
8
+ # all_day :boolean default(FALSE)
9
+ # start_time :time
10
+ # end_time :time
11
+ # status :string(255) default("pending")
12
+ # user_id :integer
13
+ # created_at :datetime
14
+ # updated_at :datetime
15
+ # off_date :date
16
+ # approved_date :datetime
17
+ # approved_by :integer
18
+ # cancelled_date :datetime
19
+ # vacation :boolean default(FALSE)
20
+ #
21
+
22
+ class Timeoff < ActiveRecord::Base
23
+ belongs_to :user
24
+ validates_presence_of :user
25
+ validates_inclusion_of :day_of_week, :in => 0..6
26
+ validates_date :off_date, :on => :create, :on_or_after => :today
27
+ validates_time :start_time, :if => lambda { self.all_day == false }
28
+ validates_time :end_time, :after => :start_time, :if => lambda { self.all_day == false }
29
+
30
+ # before_save :create_vacation_info
31
+
32
+ def all_day_absence?
33
+ self.all_day == true
34
+ end
35
+
36
+ def approved?
37
+ self.status == 'approved'
38
+ end
39
+
40
+ def interfere?(start_time, end_time)
41
+ if ( self.start_time < start_time && self.end_time > start_time ) ||
42
+ ( end_time > self.start_time && end_time < self.end_time ) ||
43
+ ( self.start_time > start_time && self.end_time < end_time )
44
+ true
45
+ else
46
+ false
47
+ end
48
+ end
49
+
50
+ def detail
51
+ return "Your TimeOff Request for #{off_date} has been approved"
52
+ end
53
+
54
+ def formatted_due_date
55
+ "#{off_date.strftime('%A')},#{off_date.strftime('%B')} #{off_date.day}, #{off_date.year}"
56
+ end
57
+
58
+ def approve(manager)
59
+ create_vacation_info
60
+ self.approved_by = manager.id
61
+ self.approved_date = DateTime.now
62
+ self.status = 'approved'
63
+ save
64
+ end
65
+
66
+ def cancel
67
+ self.status = 'cancelled'
68
+ self.cancelled_date = DateTime.now
69
+ save
70
+ end
71
+
72
+ private
73
+ def create_vacation_info
74
+ if self.vacation
75
+ if self.user.user_vacation_info
76
+ already_spent_hours = self.user.user_vacation_info.spent_hours
77
+ if self.all_day
78
+ new_spent_hours = already_spent_hours + 24
79
+ else
80
+ new_spent_hours = already_spent_hours + (end_time - start_time)/3600
81
+ end
82
+
83
+ self.user.user_vacation_info.update_attribute(:spent_hours, new_spent_hours)
84
+ else
85
+ if self.all_day
86
+ new_spent_hours = 24
87
+ else
88
+ new_spent_hours = end_time - start_time
89
+ end
90
+
91
+ if self.user.vacation
92
+ user_vacation_info = UserVacationInfo.create(:user_id => self.user_id,
93
+ :vacation_id => self.user.vacation.id,
94
+ :spent_hours => new_spent_hours
95
+ )
96
+ end
97
+ end
98
+ end
99
+ end
100
+
101
+ end