erp_work_effort 4.0.0 → 4.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/api/v1/projects_controller.rb +25 -0
  3. data/app/controllers/api/v1/time_entries_controller.rb +313 -0
  4. data/app/controllers/api/v1/transportation_routes_controller.rb +9 -0
  5. data/app/controllers/api/v1/work_effort_associations_controller.rb +102 -0
  6. data/app/controllers/api/v1/work_effort_party_assignments_controller.rb +136 -0
  7. data/app/controllers/api/v1/work_effort_types_controller.rb +120 -0
  8. data/app/controllers/api/v1/work_efforts_controller.rb +284 -0
  9. data/app/models/associated_transportation_route.rb +8 -5
  10. data/app/models/cal_evt_party_role.rb +9 -0
  11. data/app/models/calendar_event.rb +46 -0
  12. data/app/models/calendar_invite.rb +10 -0
  13. data/app/models/candidate_submission.rb +37 -0
  14. data/app/models/experience.rb +11 -0
  15. data/app/models/extensions/biz_txn_events.rb +35 -0
  16. data/app/models/extensions/finacial_txns.rb +27 -0
  17. data/app/models/extensions/order_line_item.rb +12 -0
  18. data/app/models/extensions/party.rb +204 -0
  19. data/app/models/party_skill.rb +2 -0
  20. data/app/models/pay_period.rb +59 -0
  21. data/app/models/position.rb +8 -0
  22. data/app/models/position_fulfillment.rb +8 -0
  23. data/app/models/position_type.rb +12 -0
  24. data/app/models/project.rb +59 -0
  25. data/app/models/requirement.rb +2 -0
  26. data/app/models/resume.rb +11 -0
  27. data/app/models/shift.rb +22 -0
  28. data/app/models/skill_type.rb +8 -0
  29. data/app/models/staffing_position.rb +9 -0
  30. data/app/models/time_entry.rb +260 -0
  31. data/app/models/timesheet.rb +194 -0
  32. data/app/models/timesheet_party_role.rb +21 -0
  33. data/app/models/transportation_route.rb +103 -18
  34. data/app/models/transportation_route_segment.rb +44 -0
  35. data/app/models/transportation_route_stop.rb +19 -0
  36. data/app/models/wc_code.rb +7 -0
  37. data/app/models/work_effort.rb +512 -30
  38. data/app/models/work_effort_association.rb +7 -0
  39. data/app/models/work_effort_association_type.rb +5 -0
  40. data/app/models/work_effort_biz_txn_event.rb +22 -0
  41. data/app/models/work_effort_party_assignment.rb +140 -3
  42. data/app/models/work_effort_type.rb +5 -0
  43. data/config/routes.rb +54 -11
  44. data/db/data_migrations/20150709053041_add_skill_types.rb +27 -0
  45. data/db/data_migrations/20150709055922_add_position_types.rb +27 -0
  46. data/db/data_migrations/20150711220000_add_task_tracked_statuses.rb +25 -0
  47. data/db/data_migrations/20150712081804_add_work_effort_types.rb +23 -0
  48. data/db/data_migrations/20150718052204_add_project_tracked_statuses.rb +24 -0
  49. data/db/data_migrations/20150718054404_add_project_party_role_types.rb +14 -0
  50. data/db/data_migrations/20150812150320_add_work_effort_dependency_types.rb +35 -0
  51. data/db/migrate/20100220000000_base_work_efforts.rb +310 -89
  52. data/db/migrate/20150227174108_create_staffing_positions.rb +11 -0
  53. data/db/migrate/20150305194158_create_wc_codes.rb +24 -0
  54. data/db/migrate/20150313134411_create_shifts.rb +28 -0
  55. data/db/migrate/20150325195749_create_candidate_submissions.rb +22 -0
  56. data/db/migrate/20150327115910_resumes.rb +15 -0
  57. data/db/migrate/20150401060938_add_resume_parser_statuses.rb +14 -0
  58. data/db/migrate/20150607181734_create_calendar_events.rb +24 -0
  59. data/db/migrate/20150616174228_create_cal_evt_party_roles.rb +19 -0
  60. data/db/migrate/20150707164520_create_calendar_invites.rb +21 -0
  61. data/db/migrate/20150718052404_create_projects.rb +20 -0
  62. data/db/migrate/20150812191812_update_work_efforts.rb +59 -0
  63. data/db/migrate/20150824152639_add_sequence_to_work_effort.rb +9 -0
  64. data/db/migrate/20150830133951_add_work_effort_biz_txn_events.rb +21 -0
  65. data/db/migrate/20150908200612_update_time_entries.rb +70 -0
  66. data/db/migrate/20151115180427_add_defaults_for_work_effort.rb +36 -0
  67. data/db/migrate/20151218195330_update_transportation_routes.rb +72 -0
  68. data/db/migrate/20160310163052_add_created_by_updated_by_to_erp_work_effort.rb +63 -0
  69. data/db/migrate/20160418115227_add_created_by_updated_by_to_skill_type.rb +34 -0
  70. data/lib/erp_work_effort.rb +3 -0
  71. data/lib/erp_work_effort/config.rb +33 -0
  72. data/lib/erp_work_effort/engine.rb +0 -4
  73. data/lib/erp_work_effort/services/unit_converter.rb +284 -0
  74. data/lib/erp_work_effort/version.rb +1 -1
  75. data/lib/tasks/populate_model_data.rake +19 -0
  76. data/lib/tasks/resume_parser.rake +18 -0
  77. metadata +80 -16
  78. data/app/controllers/erp_work_effort/erp_app/organizer/tasks/base_controller.rb +0 -13
  79. data/app/controllers/erp_work_effort/erp_app/organizer/tasks/work_efforts_controller.rb +0 -128
  80. data/db/data_migrations/20131213151309_create_tasks_organizer_application.rb +0 -14
  81. data/db/migrate/20130829153419_base_routes.rb +0 -93
  82. data/db/migrate/20131213140617_add_work_effort_role_assignments.rb +0 -16
  83. data/db/migrate/20131213144223_add_work_item_to_work_effort.rb +0 -8
  84. data/db/migrate/20140106184615_update_work_effort_item_id_to_int.rb +0 -27
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ad5d23963efb2e5067ac139ef8d7886811a058d1
4
- data.tar.gz: 0d51e61b9b9b83fe5d6080a4a543cffa27bc9c8f
3
+ metadata.gz: b58acc4d8a198a71e9c42ac9daa6b9d977aa5fef
4
+ data.tar.gz: f7b3fb86a17d31ac9b3dde1e428140c5e2ec1449
5
5
  SHA512:
6
- metadata.gz: 7f7a8b18fa29c8584836be2c62a412575163c2ea82acb3d9c8d5106a507efbe704c32ae7b46968949fbbcd765fc7235ab3f5e08ac41fb8a759655cda9a1ad0e3
7
- data.tar.gz: d775e88305f33b49f9e54e0520638cf70b6bc408606f89acb994449f0204c55e6eaaf8260c3df506540434270c1bf2e6069e5e0dbc542a54f39fd52958d769f6
6
+ metadata.gz: c132f84cd49fa0c36acd5b11731e542007f7f9dc2bee440a685d91753b35210cd7a78a7d23fd8b7cccb8695d91d27bd126805465accbfa0e751bb7d8bae9c9b9
7
+ data.tar.gz: b9789ee3069d3201144cce1a6419ad7ec2c287475d22fa8f0f7cc8b105c156ede8b98022f40692a2534ba10c254456f9414ac3dba3bdc896652e46f6bed27ba6
@@ -0,0 +1,25 @@
1
+ module Api
2
+ module V1
3
+ class ProjectsController < BaseController
4
+
5
+ def index
6
+ # check if we are scoping by current user
7
+ if params[:scope_by_user].present? and params[:scope_by_user].to_bool
8
+ party = current_user.party
9
+ projects = Project.scope_by_party(party,
10
+ {role_types: RoleType.find_child_role_types(party.party_roles.collect { |party_role| party_role.role_type })})
11
+ else
12
+ # scope by dba organization
13
+ projects = Project.scope_by_dba_organization(current_user.party.dba_organization)
14
+ end
15
+
16
+ if params[:query]
17
+ projects = projects.where(projects.arel_table[:description].matches("%#{params[:query]}%"))
18
+ end
19
+
20
+ render :json => {success: true, projects: projects.all.map { |project| project.to_data_hash }}
21
+ end
22
+
23
+ end # ProjectsController
24
+ end # V1
25
+ end # Api
@@ -0,0 +1,313 @@
1
+ module Api
2
+ module V1
3
+ class TimeEntriesController < BaseController
4
+
5
+ def create
6
+ begin
7
+ ActiveRecord::Base.connection.transaction do
8
+ party = current_user.party
9
+
10
+ time_entry = TimeEntry.new(
11
+ manual_entry: true
12
+ )
13
+
14
+ if params[:from_datetime]
15
+ time_entry.from_datetime = params[:from_datetime].to_time
16
+ end
17
+
18
+ if params[:thru_datetime]
19
+ time_entry.from_datetime = params[:thru_datetime].to_time
20
+ end
21
+
22
+ if params[:comment]
23
+ time_entry.comment = params[:comment].strip
24
+ end
25
+
26
+ if params[:regular_hours_in_seconds]
27
+ time_entry.regular_hours_in_seconds = params[:regular_hours_in_seconds].to_i
28
+ end
29
+
30
+ if params[:overtime_hours_in_seconds]
31
+ time_entry.overtime_hours_in_seconds = params[:regular_hours_in_seconds].to_i
32
+ end
33
+
34
+ if params[:work_effort_id]
35
+ time_entry.work_effort = params[:work_effort_id]
36
+ end
37
+
38
+ # if a timesheet id is passed assoicate to that timesheet if not associate to
39
+ # the current user's timesheet
40
+ if params[:timesheet_id]
41
+ time_entry.timesheet_id = params[:timesheet_id]
42
+ else
43
+ time_sheet = party.timesheets.current!(current_user.party, RoleType.iid('work_resource'))
44
+ time_entry.timesheet_id = time_sheet.id
45
+ end
46
+
47
+ render json: {
48
+ success: true,
49
+ time_entry: time_entry.to_data_hash,
50
+ }
51
+
52
+ end
53
+ rescue ActiveRecord::RecordInvalid => invalid
54
+ Rails.logger.error invalid.record.errors
55
+
56
+ render :json => {:success => false, :message => invalid.record.errors}
57
+ rescue StandardError => ex
58
+ Rails.logger.error ex.message
59
+ Rails.logger.error ex.backtrace.join("\n")
60
+
61
+ ExceptionNotifier.notify_exception(ex) if defined? ExceptionNotifier
62
+
63
+ render json: {success: false, message: 'Error creating Time Entry'}
64
+ end
65
+ end
66
+
67
+ def update
68
+ begin
69
+ ActiveRecord::Base.connection.transaction do
70
+
71
+ time_entry = TimeEntry.find(params[:id])
72
+
73
+ if params[:from_datetime]
74
+ time_entry.from_datetime = params[:from_datetime].to_time
75
+ end
76
+
77
+ if params[:thru_datetime]
78
+ time_entry.from_datetime = params[:thru_datetime].to_time
79
+ end
80
+
81
+ if params[:comment]
82
+ time_entry.comment = params[:comment].strip
83
+ end
84
+
85
+ if params[:regular_hours_in_seconds]
86
+ time_entry.regular_hours_in_seconds = params[:regular_hours_in_seconds].to_i
87
+ end
88
+
89
+ if params[:overtime_hours_in_seconds]
90
+ time_entry.overtime_hours_in_seconds = params[:regular_hours_in_seconds].to_i
91
+ end
92
+
93
+ # update to manual entry
94
+ time_entry.manual_entry = true
95
+
96
+ render json: {
97
+ success: time_entry.save!,
98
+ time_entry: time_entry.to_data_hash,
99
+ }
100
+
101
+ end
102
+ rescue ActiveRecord::RecordInvalid => invalid
103
+ Rails.logger.error invalid.record.errors
104
+
105
+ render :json => {:success => false, :message => invalid.record.errors}
106
+ rescue StandardError => ex
107
+ Rails.logger.error ex.message
108
+ Rails.logger.error ex.backtrace.join("\n")
109
+
110
+ ExceptionNotifier.notify_exception(ex) if defined? ExceptionNotifier
111
+
112
+ render json: {success: false, message: 'Error updating Time Entry'}
113
+ end
114
+ end
115
+
116
+ def show
117
+ time_entry = TimeEntry.find(params[:id])
118
+
119
+ render :json => {success: true, time_entry: time_entry.to_data_hash}
120
+ end
121
+
122
+ # start TimeEntry by setting the from_datetime but not the thru_datetime
123
+ # if there is already an open time_entry do not let another one be started
124
+ # It is assumed that a TimeEntry is always logged against a work effort so
125
+ # a WorkEffort id should be passed.
126
+ #
127
+ def start
128
+ begin
129
+ ActiveRecord::Base.connection.transaction do
130
+
131
+ party = current_user.party
132
+ work_effort = WorkEffort.find(params[:work_effort_id])
133
+
134
+ # check for an open TimeEntry
135
+ open_time_entry = party.open_time_entry
136
+
137
+ # if there is an open TimeEntry stop it and start a new one
138
+ if open_time_entry
139
+ open_time_entry.thru_datetime = Time.now
140
+
141
+ open_time_entry.calculate_regular_hours_in_seconds!
142
+ end
143
+
144
+ time_entry = TimeEntry.create(
145
+ from_datetime: params[:start_at].to_time
146
+ )
147
+
148
+ time_entry.work_effort = work_effort
149
+
150
+ # associate to a timesheet
151
+ time_sheet = party.timesheets.current!(RoleType.iid('work_resource'))
152
+ time_sheet.time_entries << time_entry
153
+
154
+ # update task statuses
155
+ time_entry.update_task_status('task_status_in_progress')
156
+ time_entry.update_task_assignment_status('task_resource_status_in_progress')
157
+
158
+ render json: {
159
+ success: true,
160
+ time_entry: time_entry.to_data_hash,
161
+ }
162
+ end
163
+ rescue ActiveRecord::RecordInvalid => invalid
164
+ Rails.logger.error invalid.record.errors
165
+
166
+ render :json => {:success => false, :message => invalid.record.errors}
167
+ rescue StandardError => ex
168
+ Rails.logger.error ex.message
169
+ Rails.logger.error ex.backtrace.join("\n")
170
+
171
+ ExceptionNotifier.notify_exception(ex) if defined? ExceptionNotifier
172
+
173
+ render json: {success: false, message: 'Error starting Time Entry'}
174
+ end
175
+ end
176
+
177
+ # stop TimeEntry by setting the thru_datetime and calculating the hours in seconds
178
+ # it returns the TimeEntry record as well as formatted totals for the day and week
179
+ #
180
+ def stop
181
+ begin
182
+ ActiveRecord::Base.connection.transaction do
183
+ party = current_user.party
184
+ work_effort = WorkEffort.find(params[:work_effort_id])
185
+ time_entry = TimeEntry.find(params[:id])
186
+
187
+ time_entry.thru_datetime = params[:end_at].to_time
188
+ time_entry.comment = params[:comment].present? ? params[:comment].strip : nil
189
+
190
+ time_entry.calculate_regular_hours_in_seconds!
191
+
192
+ time_entry.update_task_assignment_status('task_resource_status_hold')
193
+
194
+ result = {
195
+ success: true,
196
+ time_entry: time_entry.to_data_hash,
197
+ }
198
+
199
+ time_helper = ErpBaseErpSvcs::Helpers::Time::Client.new(params[:client_utc_offset])
200
+
201
+ result[:day_total_formatted] = TimeEntry.total_formatted(work_effort: work_effort,
202
+ party: party,
203
+ start: time_helper.beginning_of_day,
204
+ end: time_helper.end_of_day
205
+ )
206
+ result[:week_total_formatted] = TimeEntry.total_formatted(work_effort: work_effort,
207
+ party: party,
208
+ start: time_helper.beginning_of_week,
209
+ end: time_helper.end_of_week
210
+ )
211
+
212
+ render json: result
213
+ end
214
+ rescue ActiveRecord::RecordInvalid => invalid
215
+ Rails.logger.error invalid.record.errors
216
+
217
+ render :json => {:success => false, :message => invalid.record.errors}
218
+ rescue StandardError => ex
219
+ Rails.logger.error ex.message
220
+ Rails.logger.error ex.backtrace.join("\n")
221
+
222
+ ExceptionNotifier.notify_exception(ex) if defined? ExceptionNotifier
223
+
224
+ render json: {success: false, message: 'Error stopping Time Entry'}
225
+ end
226
+ end
227
+
228
+ # if a work effort id is passed get the last open time_entry for that work_effort
229
+ # for the current user if there are no open time entries then return only the totals
230
+ #
231
+ def open
232
+ if params[:work_effort_id]
233
+ work_effort = WorkEffort.find(params[:work_effort_id])
234
+ party = current_user.party
235
+
236
+ open_time_entry = work_effort.time_entries.scope_by_party(current_user.party).open_entries.first
237
+ time_helper = ErpBaseErpSvcs::Helpers::Time::Client.new(params[:client_utc_offset])
238
+
239
+ render :json => {success: true,
240
+ time_entry: open_time_entry.nil? ? nil : open_time_entry.to_data_hash,
241
+ day_total_formatted: TimeEntry.total_formatted(work_effort: work_effort,
242
+ party: party,
243
+ start: time_helper.beginning_of_day,
244
+ end: time_helper.end_of_day),
245
+ week_total_formatted: TimeEntry.total_formatted(work_effort: work_effort,
246
+ party: party,
247
+ start: time_helper.beginning_of_week,
248
+ end: time_helper.end_of_week)
249
+ }
250
+ else
251
+ render :json => {success: true, time_entries: TimeEntry.open_entries.collect { |time_entry| time_entry.to_data_hash }}
252
+ end
253
+ end
254
+
255
+ # returns totals for time entries. If a work effort id is passed it will get totals for the
256
+ # passed work effort. If no work effort id is passed it will get totals for the current user
257
+ # passed on their timesheet
258
+ #
259
+ def totals
260
+ result = {
261
+ success: true,
262
+ day_total_seconds: 0,
263
+ week_total_seconds: 0,
264
+ day_total_formatted: '00:00:00',
265
+ week_total_formatted: '00:00:00',
266
+ total_formatted: '00:00:00'
267
+ }
268
+
269
+ work_effort = nil
270
+ party = nil
271
+ time_helper = ErpBaseErpSvcs::Helpers::Time::Client.new(params[:client_utc_offset])
272
+
273
+ if params[:work_effort_id]
274
+ work_effort = WorkEffort.find(params[:work_effort_id])
275
+ end
276
+
277
+ if params[:party_id]
278
+ party = Party.find(params[:party_id])
279
+ end
280
+
281
+ result[:day_total_seconds] = TimeEntry.total_seconds(work_effort: work_effort,
282
+ party: party,
283
+ start: time_helper.beginning_of_day,
284
+ end: time_helper.end_of_day
285
+ )
286
+ result[:week_total_seconds] = TimeEntry.total_seconds(work_effort: work_effort,
287
+ party: party,
288
+ start: time_helper.beginning_of_week,
289
+ end: time_helper.end_of_week
290
+ )
291
+ result[:total_seconds] = TimeEntry.total_seconds(work_effort: work_effort,
292
+ party: party
293
+ )
294
+ result[:day_total_formatted] = TimeEntry.total_formatted(work_effort: work_effort,
295
+ party: party,
296
+ start: time_helper.beginning_of_day,
297
+ end: time_helper.end_of_day
298
+ )
299
+ result[:week_total_formatted] = TimeEntry.total_formatted(work_effort: work_effort,
300
+ party: party,
301
+ start: time_helper.beginning_of_week,
302
+ end: time_helper.end_of_week
303
+ )
304
+ result[:total_formatted] = TimeEntry.total_formatted(work_effort: work_effort,
305
+ party: party
306
+ )
307
+
308
+ render json: result
309
+ end
310
+
311
+ end # TimeEntriesController
312
+ end # V1
313
+ end # Api
@@ -0,0 +1,9 @@
1
+ module Api
2
+ module V1
3
+ class TransportationRoutesController < BaseController
4
+
5
+ # TODO implement CRUD operations
6
+
7
+ end # TransportationRoutesController
8
+ end # V1
9
+ end # Api
@@ -0,0 +1,102 @@
1
+ module Api
2
+ module V1
3
+ class WorkEffortAssociationsController < BaseController
4
+
5
+ def index
6
+ work_effort_associations = WorkEffortAssociation
7
+
8
+ if params[:project_id]
9
+ work_effort_associations = work_effort_associations.joins('inner join work_efforts on work_efforts.id = work_effort_associations.work_effort_id_to')
10
+ .where('work_efforts.project_id = ?', params[:project_id])
11
+ else
12
+ # scope by dba organization
13
+ work_effort_associations = work_effort_associations.joins('inner join work_efforts on work_efforts.id = work_effort_associations.work_effort_id_to')
14
+ .joins("inner join entity_party_roles on entity_party_roles.entity_record_type = 'WorkEffort' and entity_party_roles.entity_record_id = work_efforts.id")
15
+ .where('entity_party_roles.party_id = ? and entity_party_roles.role_type_id = ?', current_user.party.dba_organization.id, RoleType.iid('dba_org').id)
16
+ end
17
+
18
+ render :json => {success: true, work_effort_associations: work_effort_associations.all.map { |work_effort| work_effort.to_data_hash }}
19
+ end
20
+
21
+ def show
22
+ render :json => {success: true, work_effort_association: WorkEffortAssociation.find(params[:id]).to_data_hash}
23
+ end
24
+
25
+ def create
26
+ begin
27
+ ActiveRecord::Base.connection.transaction do
28
+
29
+ work_effort_association = WorkEffortAssociation.new
30
+ work_effort_association.work_effort_id_from = params[:work_effort_id_from]
31
+ work_effort_association.work_effort_id_to = params[:work_effort_id_to]
32
+ work_effort_association.work_effort_association_type = WorkEffortAssociationType.where('external_identifier = ?', params['work_effort_association_type.external_identifier'].to_s).first
33
+
34
+ work_effort_association.save!
35
+
36
+ render :json => {success: true, work_effort_association: work_effort_association.to_data_hash}
37
+
38
+ end
39
+ rescue ActiveRecord::RecordInvalid => invalid
40
+ Rails.logger.error invalid.record.errors
41
+
42
+ render :json => {:success => false, :message => invalid.record.errors}
43
+ rescue StandardError => ex
44
+ Rails.logger.error ex.message
45
+ Rails.logger.error ex.backtrace.join("\n")
46
+
47
+ ExceptionNotifier.notify_exception(ex) if defined? ExceptionNotifier
48
+
49
+ render json: {success: false, message: 'Error creating Work Effort Association'}
50
+ end
51
+ end
52
+
53
+ def update
54
+ begin
55
+ ActiveRecord::Base.connection.transaction do
56
+
57
+ work_effort_association = WorkEffortAssociation.find(params[:id])
58
+ work_effort_association.work_effort_id_from = params[:work_effort_id_from]
59
+ work_effort_association.work_effort_id_to = params[:work_effort_id_to]
60
+ work_effort_association.work_effort_association_type = WorkEffortAssociationType.where('external_identifier = ?', params[:work_effort_association_type_external_id].to_s).first
61
+
62
+ work_effort_association.save!
63
+
64
+ render :json => {success: true, work_effort_association: work_effort_association.to_data_hash}
65
+
66
+ end
67
+ rescue ActiveRecord::RecordInvalid => invalid
68
+ Rails.logger.error invalid.record.errors
69
+
70
+ render :json => {:success => false, :message => invalid.record.errors}
71
+ rescue StandardError => ex
72
+ Rails.logger.error ex.message
73
+ Rails.logger.error ex.backtrace.join("\n")
74
+
75
+ ExceptionNotifier.notify_exception(ex) if defined? ExceptionNotifier
76
+
77
+ render json: {success: false, message: 'Error updating Work Effort Association'}
78
+ end
79
+ end
80
+
81
+ def destroy
82
+ work_effort_association = WorkEffortAssociation.find(params[:id])
83
+
84
+ begin
85
+ ActiveRecord::Base.connection.transaction do
86
+
87
+ render json: {success: work_effort_association.destroy}
88
+
89
+ end
90
+ rescue StandardError => ex
91
+ Rails.logger.error ex.message
92
+ Rails.logger.error ex.backtrace.join("\n")
93
+
94
+ ExceptionNotifier.notify_exception(ex) if defined? ExceptionNotifier
95
+
96
+ render json: {success: false, message: 'Error destroying Work Effort Association'}
97
+ end
98
+ end
99
+
100
+ end # WorkEffortAssociationsController
101
+ end # V1
102
+ end # Api