canvas_sync 0.13.0 → 0.16.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/lib/canvas_sync.rb +69 -15
  3. data/lib/canvas_sync/concerns/api_syncable.rb +1 -1
  4. data/lib/canvas_sync/concerns/legacy_columns.rb +5 -4
  5. data/lib/canvas_sync/generators/templates/migrations/create_group_memberships.rb +18 -0
  6. data/lib/canvas_sync/generators/templates/migrations/create_groups.rb +23 -0
  7. data/lib/canvas_sync/generators/templates/migrations/create_pseudonyms.rb +18 -0
  8. data/lib/canvas_sync/generators/templates/migrations/create_submissions.rb +1 -0
  9. data/lib/canvas_sync/generators/templates/models/account.rb +4 -0
  10. data/lib/canvas_sync/generators/templates/models/course.rb +1 -0
  11. data/lib/canvas_sync/generators/templates/models/group.rb +19 -0
  12. data/lib/canvas_sync/generators/templates/models/group_membership.rb +17 -0
  13. data/lib/canvas_sync/generators/templates/models/pseudonym.rb +8 -0
  14. data/lib/canvas_sync/generators/templates/models/submission.rb +1 -0
  15. data/lib/canvas_sync/generators/templates/models/user.rb +2 -0
  16. data/lib/canvas_sync/jobs/sync_provisioning_report_job.rb +2 -0
  17. data/lib/canvas_sync/processors/model_mappings.yml +81 -0
  18. data/lib/canvas_sync/processors/provisioning_report_processor.rb +28 -0
  19. data/lib/canvas_sync/version.rb +1 -1
  20. data/spec/canvas_sync/canvas_sync_spec.rb +5 -2
  21. data/spec/canvas_sync/models/accounts_spec.rb +3 -0
  22. data/spec/canvas_sync/models/course_spec.rb +4 -0
  23. data/spec/canvas_sync/models/group_membership_spec.rb +26 -0
  24. data/spec/canvas_sync/models/group_spec.rb +26 -0
  25. data/spec/canvas_sync/models/user_spec.rb +2 -0
  26. data/spec/canvas_sync/processors/provisioning_report_processor_spec.rb +20 -0
  27. data/spec/dummy/app/models/account.rb +1 -0
  28. data/spec/dummy/app/models/course.rb +1 -0
  29. data/spec/dummy/app/models/group.rb +25 -0
  30. data/spec/dummy/app/models/group_membership.rb +23 -0
  31. data/spec/dummy/app/models/user.rb +1 -0
  32. data/spec/dummy/db/migrate/20190702203627_create_submissions.rb +1 -0
  33. data/spec/dummy/db/migrate/20200415171620_create_groups.rb +29 -0
  34. data/spec/dummy/db/migrate/20200416214248_create_group_memberships.rb +24 -0
  35. data/spec/dummy/db/schema.rb +31 -1
  36. data/spec/factories/group_factory.rb +8 -0
  37. data/spec/factories/group_membership_factory.rb +6 -0
  38. data/spec/support/fixtures/reports/group_memberships.csv +3 -0
  39. data/spec/support/fixtures/reports/groups.csv +3 -0
  40. data/spec/support/fixtures/reports/submissions.csv +3 -3
  41. metadata +33 -10
  42. data/lib/canvas_sync/jobs/sync_users_job.rb +0 -26
  43. data/spec/canvas_sync/jobs/sync_users_job_spec.rb +0 -15
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5c8386afbd924c0148b5c2158d23ea7acd5b0b85349da51312103e1ea9368c54
4
- data.tar.gz: 051471b40b5a464b66df8ca7ae482874f2791c55604e28f7fe9ce54cb07f875a
3
+ metadata.gz: 3c6655d28b3ac244a94cd59da9f76f6878658bff43d1ca071dd7718b82a505ad
4
+ data.tar.gz: e8ee3801761dd8a84d80ea162ff11e079b219e1d1992788aecd49451c59efaf4
5
5
  SHA512:
6
- metadata.gz: '00742595c4797ba758ef98ab8b034545eb2193a2cae92dfc585e720c7cd9adef663ba0aadcae2c7085e19497ff74461c6d5553d49114f42dac520c8fe48ca448'
7
- data.tar.gz: d8c7eb61e630bb65ea9aa2e86b86c03c2c1f87c151e127314c938f7d1b2438c90dfc5f5ddcc4cb74fe0b525bc4ef9c03dfb140d09fc10045b2f7f56b41524e43
6
+ metadata.gz: 47a9f7e858cb510f191d1c62f99f112384dc62d3d9d62365369bad5b275d0168d1d5ace94a32b7f76921ee072ae49d3b940e6d56c2aeb51601e9daf52c86b36e
7
+ data.tar.gz: 84c5b5c9816a2ff8578bb32892739a8737fb6049526f24ef1416d7a5f404fc385f808ca9a7739b1d971baf06f81fe172351015332fe56a67a2e64417158e60d3
@@ -22,7 +22,10 @@ Dir[File.dirname(__FILE__) + "/canvas_sync/concerns/**/*.rb"].each { |file| req
22
22
  module CanvasSync
23
23
  SUPPORTED_MODELS = %w[
24
24
  users
25
+ pseudonyms
25
26
  courses
27
+ groups
28
+ group_memberships
26
29
  accounts
27
30
  terms
28
31
  enrollments
@@ -143,6 +146,10 @@ module CanvasSync
143
146
  terms.each do |t|
144
147
  return scope.send(t) if scope.respond_to?(t)
145
148
  end
149
+ model = scope.try(:model) || scope
150
+ if model.try(:column_names)&.include?(:workflow_state)
151
+ return scope.where.not(workflow_state: %w[deleted])
152
+ end
146
153
  Rails.logger.warn("Could not filter Syncable Scope for model '#{scope.try(:model)&.name || scope.name}'")
147
154
  scope
148
155
  end
@@ -193,7 +200,6 @@ module CanvasSync
193
200
  model_job_map = {
194
201
  terms: CanvasSync::Jobs::SyncTermsJob,
195
202
  accounts: CanvasSync::Jobs::SyncAccountsJob,
196
- users: CanvasSync::Jobs::SyncUsersJob,
197
203
  roles: CanvasSync::Jobs::SyncRolesJob,
198
204
  admins: CanvasSync::Jobs::SyncAdminsJob,
199
205
 
@@ -221,35 +227,41 @@ module CanvasSync
221
227
 
222
228
  # Accounts, users, roles, and admins are synced before provisioning because they cannot be scoped to term
223
229
  try_add_model_job.call('accounts')
224
- try_add_model_job.call('users') if term_scope.present?
230
+
231
+ # These Models use the provisioning report, but are not term-scoped,
232
+ # so we sync them before to ensure work is not duplicated
233
+ if term_scope.present?
234
+ models -= (first_provisioning_models = models & ['users', 'pseudonyms'])
235
+ jobs.concat(
236
+ generate_provisioning_jobs(first_provisioning_models, options)
237
+ )
238
+ end
239
+
225
240
  try_add_model_job.call('roles')
226
241
  try_add_model_job.call('admins')
227
-
228
242
  pre_provisioning_jobs = jobs
229
- jobs = []
230
243
 
231
244
  ###############################
232
245
  # Post provisioning report jobs
233
246
  ###############################
234
247
 
248
+ jobs = []
235
249
  try_add_model_job.call('assignments')
236
250
  try_add_model_job.call('submissions')
237
251
  try_add_model_job.call('assignment_groups')
238
252
  try_add_model_job.call('context_modules')
239
253
  try_add_model_job.call('context_module_items')
240
-
241
254
  post_provisioning_jobs = jobs
242
255
 
243
- jobs = pre_provisioning_jobs
244
- if models.present?
245
- provisioning_job = {
246
- job: CanvasSync::Jobs::SyncProvisioningReportJob.to_s,
247
- options: { term_scope: term_scope, models: models },
248
- }
249
- provisioning_job[:options].merge!(options[:provisioning]) if options[:provisioning].present?
250
- jobs += Array.wrap(provisioning_job)
251
- end
252
- jobs += post_provisioning_jobs
256
+ ###############################
257
+ # Main provisioning job and queueing
258
+ ###############################
259
+
260
+ jobs = [
261
+ *pre_provisioning_jobs,
262
+ *generate_provisioning_jobs(models, options, job_options: { term_scope: term_scope }, only_split: ['users']),
263
+ *post_provisioning_jobs,
264
+ ]
253
265
 
254
266
  global_options = { legacy_support: legacy_support }
255
267
  global_options[:account_id] = account_id if account_id.present?
@@ -258,6 +270,48 @@ module CanvasSync
258
270
  JobChain.new(jobs: jobs, global_options: global_options)
259
271
  end
260
272
 
273
+ def group_by_job_options(model_list, options_hash, only_split: nil, default_key: :provisioning)
274
+ dup_models = [ *model_list ]
275
+ unique_option_models = {}
276
+
277
+ filtered_models = only_split ? (only_split & model_list) : model_list
278
+ filtered_models.each do |m|
279
+ mopts = options_hash[m.to_sym] || options_hash[default_key]
280
+ unique_option_models[mopts] ||= []
281
+ unique_option_models[mopts] << m
282
+ dup_models.delete(m)
283
+ end
284
+
285
+ if dup_models.present?
286
+ mopts = options_hash[default_key]
287
+ unique_option_models[mopts] ||= []
288
+ unique_option_models[mopts].concat(dup_models)
289
+ end
290
+
291
+ unique_option_models
292
+ end
293
+
294
+ def generate_provisioning_jobs(model_list, options_hash, job_options: {}, only_split: nil, default_key: :provisioning)
295
+ # Group the model options as best we can.
296
+ # This is mainly for backwards compatibility, since 'users' was previously it's own job
297
+ unique_option_models = group_by_job_options(
298
+ model_list,
299
+ options_hash,
300
+ only_split: only_split,
301
+ default_key: default_key,
302
+ )
303
+
304
+ unique_option_models.map do |mopts, models|
305
+ opts = { models: models }
306
+ opts.merge!(job_options)
307
+ opts.merge!(mopts) if mopts.present?
308
+ {
309
+ job: CanvasSync::Jobs::SyncProvisioningReportJob.to_s,
310
+ options: opts,
311
+ }
312
+ end
313
+ end
314
+
261
315
  # Calls the canvas_sync_client in your app. If you have specified an account
262
316
  # ID when starting the job it will pass the account ID to your canvas_sync_client method.
263
317
  #
@@ -146,7 +146,7 @@ module CanvasSync::Concerns
146
146
  # Apply a response Hash from the API to this model's attributes and save if changed?
147
147
  # @param [Hash] api_params API-format Hash
148
148
  # @return [self] self
149
- def update_from_api_params(api_params, **kwargs)
149
+ def update_from_api_params(*args)
150
150
  assign_from_api_params(*args)
151
151
  save if changed?
152
152
  end
@@ -15,13 +15,14 @@ module CanvasSync::Concerns
15
15
  private
16
16
 
17
17
  def legacy_column_apply(cls)
18
- cid_column = "canvas_#{subclass.name.downcase}_id"
19
- column_names = subclass.columns.map(&:name)
18
+ return if cls.abstract_class
19
+ cid_column = "canvas_#{cls.name.downcase}_id"
20
+ column_names = cls.columns.map(&:name)
20
21
  return if column_names.include?('canvas_id') && column_names.include?(cid_column)
21
22
  if column_names.include?('canvas_id')
22
- subclass.alias_attribute(cid_column.to_sym, :canvas_id)
23
+ cls.alias_attribute(cid_column.to_sym, :canvas_id)
23
24
  elsif column_names.include?(cid_column)
24
- subclass.alias_attribute(:canvas_id, cid_column.to_sym)
25
+ cls.alias_attribute(:canvas_id, cid_column.to_sym)
25
26
  end
26
27
  rescue ActiveRecord::StatementInvalid
27
28
  end
@@ -0,0 +1,18 @@
1
+ # <%= autogenerated_migration_warning %>
2
+
3
+ class CreateGroupMemberships < ActiveRecord::Migration[5.1]
4
+ def change
5
+ create_table :group_memberships do |t|
6
+ t.bigint :canvas_id, null: false
7
+ t.bigint :canvas_user_id, null: false
8
+ t.bigint :canvas_group_id, null: false
9
+ t.string :group_sis_id
10
+ t.string :user_sis_id
11
+ t.string :workflow_state
12
+
13
+ t.timestamps
14
+ end
15
+
16
+ add_index :group_memberships, :canvas_id, unique: true
17
+ end
18
+ end
@@ -0,0 +1,23 @@
1
+ # <%= autogenerated_migration_warning %>
2
+
3
+ class CreateGroups < ActiveRecord::Migration[5.1]
4
+ def change
5
+ create_table :groups do |t|
6
+ t.bigint :canvas_id, null: false
7
+ t.string :sis_id
8
+ t.bigint :canvas_group_category_id
9
+ t.string :group_category_sis_id
10
+ t.bigint :canvas_account_id
11
+ t.bigint :canvas_course_id
12
+ t.string :name
13
+ t.string :workflow_state
14
+ t.bigint :context_id
15
+ t.string :context_type
16
+ t.integer :max_membership
17
+
18
+ t.timestamps
19
+ end
20
+
21
+ add_index :groups, :canvas_id, unique: true
22
+ end
23
+ end
@@ -0,0 +1,18 @@
1
+ # <%= autogenerated_migration_warning %>
2
+
3
+ class CreatePseudonyms < ActiveRecord::Migration[5.1]
4
+ def change
5
+ create_table :pseudonyms do |t|
6
+ t.bigint :canvas_id, null: false
7
+ t.bigint :canvas_user_id
8
+ t.string :sis_id
9
+ t.string :unique_id
10
+ t.string :workflow_state
11
+
12
+ t.timestamps
13
+ end
14
+
15
+ add_index :pseudonyms, :canvas_id, unique: true
16
+ add_index :pseudonyms, :canvas_user_id
17
+ end
18
+ end
@@ -8,6 +8,7 @@ class CreateSubmissions < ActiveRecord::Migration[5.1]
8
8
  t.bigint :canvas_assignment_id
9
9
  t.bigint :canvas_user_id
10
10
  t.datetime :submitted_at
11
+ t.datetime :due_at
11
12
  t.datetime :graded_at
12
13
  t.float :score
13
14
  t.float :points_possible
@@ -12,6 +12,10 @@ class Account < ApplicationRecord
12
12
  primary_key: :canvas_id, foreign_key: :canvas_parent_account_id
13
13
  has_many :sub_accounts, class_name: 'Account',
14
14
  primary_key: :canvas_id, foreign_key: :canvas_parent_account_id
15
+ has_many :groups, primary_key: :canvas_id, foreign_key: :canvas_account_id
16
+
17
+ scope :active, -> { where.not(workflow_state: 'deleted') }
18
+ # scope :should_canvas_sync, -> { active } # Optional - uses .active if not given
15
19
 
16
20
  api_syncable({
17
21
  name: :name,
@@ -11,6 +11,7 @@ class Course < ApplicationRecord
11
11
  has_many :assignments, as: :context, primary_key: :canvas_id, foreign_key: :canvas_context_id, foreign_type: :canvas_context_type
12
12
  has_many :submissions, primary_key: :canvas_id, foreign_key: :canvas_course_id
13
13
  has_many :assignment_groups, primary_key: :canvas_id, foreign_key: :canvas_course_id
14
+ has_many :groups, primary_key: :canvas_id, foreign_key: :canvas_course_id
14
15
 
15
16
  api_syncable({
16
17
  sis_id: :sis_course_id,
@@ -0,0 +1,19 @@
1
+ # <%= autogenerated_model_warning %>
2
+
3
+ class Group < ApplicationRecord
4
+ include CanvasSync::Record
5
+ include CanvasSync::Concerns::ApiSyncable
6
+
7
+ validates :canvas_id, uniqueness: true, presence: true
8
+ belongs_to :course, primary_key: :canvas_id, foreign_key: :canvas_course_id, optional: true
9
+ belongs_to :account, primary_key: :canvas_id, foreign_key: :canvas_account_id, optional: true
10
+ has_many :group_memberships, primary_key: :canvas_id, foreign_key: :canvas_group_id
11
+
12
+ api_syncable({
13
+ canvas_id: :id,
14
+ name: :name,
15
+ canvas_course_id: :course_id,
16
+ sis_id: :sis_group_id,
17
+ workflow_state: ->(r){ 'available' },
18
+ }, -> (api) { api.group(canvas_id) })
19
+ end
@@ -0,0 +1,17 @@
1
+ # <%= autogenerated_model_warning %>
2
+
3
+ class GroupMembership < ApplicationRecord
4
+ include CanvasSync::Record
5
+ include CanvasSync::Concerns::ApiSyncable
6
+
7
+ validates :canvas_id, uniqueness: true, presence: true
8
+ belongs_to :group, primary_key: :canvas_id, foreign_key: :canvas_group_id
9
+ belongs_to :user, primary_key: :canvas_id, foreign_key: :canvas_user_id
10
+
11
+ api_syncable({
12
+ canvas_id: :id,
13
+ canvas_group_id: :group_id,
14
+ canvas_user_id: :user_id,
15
+ workflow_state: :workflow_state,
16
+ }, -> (api) { api.group_membership(canvas_group_id, canvas_id) })
17
+ end
@@ -0,0 +1,8 @@
1
+ # <%= autogenerated_model_warning %>
2
+
3
+ class Pseudonym < ApplicationRecord
4
+ include CanvasSync::Record
5
+
6
+ validates :canvas_id, uniqueness: true, presence: true
7
+ belongs_to :user, primary_key: :canvas_id, foreign_key: :canvas_user_id
8
+ end
@@ -14,6 +14,7 @@ class Submission < ApplicationRecord
14
14
  canvas_user_id: :user_id,
15
15
  submitted_at: :submitted_at,
16
16
  graded_at: :graded_at,
17
+ cached_due_date: :due_at,
17
18
  score: :score,
18
19
  excused: :excused,
19
20
  workflow_state: :workflow_state,
@@ -5,10 +5,12 @@ class User < ApplicationRecord
5
5
  include CanvasSync::Concerns::ApiSyncable
6
6
 
7
7
  validates :canvas_id, uniqueness: true, presence: true
8
+ has_many :pseudonyms, primary_key: :canvas_id, foreign_key: :canvas_user_id
8
9
  has_many :enrollments, primary_key: :canvas_id, foreign_key: :canvas_user_id
9
10
  has_many :admins, primary_key: :canvas_id, foreign_key: :canvas_user_id
10
11
  has_many :admin_roles, through: :admins, source: :role
11
12
  has_many :submissions, primary_key: :canvas_id, foreign_key: :canvas_user_id
13
+ has_many :group_memberships, primary_key: :canvas_id, foreign_key: :canvas_user_id
12
14
 
13
15
  api_syncable({
14
16
  sis_id: :sis_user_id,
@@ -49,6 +49,8 @@ module CanvasSync
49
49
  }
50
50
 
51
51
  options[:models].each do |model|
52
+ # group_membership is the only model param that is singular :(
53
+ model = 'group_membership' if model == 'group_memberships'
52
54
  params[model] = true
53
55
  end
54
56
 
@@ -29,6 +29,25 @@ users:
29
29
  database_column_name: login_id
30
30
  type: string
31
31
 
32
+ pseudonyms:
33
+ conflict_target: pseudonym_id
34
+ report_columns:
35
+ pseudonym_id:
36
+ database_column_name: canvas_id
37
+ type: integer
38
+ canvas_user_id:
39
+ database_column_name: canvas_user_id
40
+ type: integer
41
+ sis_user_id:
42
+ database_column_name: sis_id
43
+ type: string
44
+ unique_id:
45
+ database_column_name: unique_id
46
+ type: string
47
+ status:
48
+ database_column_name: workflow_state
49
+ type: string
50
+
32
51
  accounts:
33
52
  conflict_target: canvas_account_id
34
53
  report_columns:
@@ -230,6 +249,9 @@ submissions:
230
249
  submission_date:
231
250
  database_column_name: submitted_at
232
251
  type: datetime
252
+ due_at:
253
+ database_column_name: due_at
254
+ type: datetime
233
255
  graded_date:
234
256
  database_column_name: graded_at
235
257
  type: datetime
@@ -326,3 +348,62 @@ context_module_items:
326
348
  assignment_id:
327
349
  database_column_name: canvas_assignment_id
328
350
  type: integer
351
+
352
+ groups:
353
+ conflict_target: canvas_group_id
354
+ report_columns:
355
+ canvas_group_id:
356
+ database_column_name: canvas_id
357
+ type: integer
358
+ group_id:
359
+ database_column_name: sis_id
360
+ type: string
361
+ canvas_group_category_id:
362
+ database_column_name: canvas_group_category_id
363
+ type: integer
364
+ group_category_id:
365
+ database_column_name: group_category_sis_id
366
+ type: integer
367
+ canvas_account_id:
368
+ database_column_name: canvas_account_id
369
+ type: integer
370
+ canvas_course_id:
371
+ database_column_name: canvas_course_id
372
+ type: integer
373
+ name:
374
+ database_column_name: name
375
+ type: string
376
+ status:
377
+ database_column_name: workflow_state
378
+ type: string
379
+ context_id:
380
+ database_column_name: context_id
381
+ type: integer
382
+ context_type:
383
+ database_column_name: context_type
384
+ type: string
385
+ max_membership:
386
+ database_column_name: max_membership
387
+ type: integer
388
+
389
+ group_memberships:
390
+ conflict_target: canvas_group_membership_id
391
+ report_columns:
392
+ canvas_group_membership_id:
393
+ database_column_name: canvas_id
394
+ type: integer
395
+ canvas_group_id:
396
+ database_column_name: canvas_group_id
397
+ type: integer
398
+ group_id:
399
+ database_column_name: group_sis_id
400
+ type: string
401
+ canvas_user_id:
402
+ database_column_name: canvas_user_id
403
+ type: integer
404
+ user_id:
405
+ database_column_name: user_sis_id
406
+ type: string
407
+ status:
408
+ database_column_name: workflow_state
409
+ type: string
@@ -78,6 +78,15 @@ module CanvasSync
78
78
  )
79
79
  end
80
80
 
81
+ def bulk_process_pseudonyms(report_file_path)
82
+ CanvasSync::Importers::BulkImporter.import(
83
+ report_file_path,
84
+ mapping[:pseudonyms][:report_columns],
85
+ Pseudonym,
86
+ mapping[:pseudonyms][:conflict_target].to_sym,
87
+ )
88
+ end
89
+
81
90
  def bulk_process_accounts(report_file_path)
82
91
  CanvasSync::Importers::BulkImporter.import(
83
92
  report_file_path,
@@ -122,6 +131,25 @@ module CanvasSync
122
131
  mapping[:xlist][:conflict_target].to_sym,
123
132
  )
124
133
  end
134
+
135
+ def bulk_process_groups(report_file_path)
136
+ CanvasSync::Importers::BulkImporter.import(
137
+ report_file_path,
138
+ mapping[:groups][:report_columns],
139
+ Group,
140
+ mapping[:groups][:conflict_target].to_sym,
141
+ )
142
+ end
143
+
144
+ # Note that group membership is singular because we override the model name param in sync_provisioning_report_job
145
+ def bulk_process_group_membership(report_file_path)
146
+ CanvasSync::Importers::BulkImporter.import(
147
+ report_file_path,
148
+ mapping[:group_memberships][:report_columns],
149
+ GroupMembership,
150
+ mapping[:group_memberships][:conflict_target].to_sym,
151
+ )
152
+ end
125
153
  end
126
154
  end
127
155
  end
@@ -1,3 +1,3 @@
1
1
  module CanvasSync
2
- VERSION = "0.13.0".freeze
2
+ VERSION = "0.16.2".freeze
3
3
  end
@@ -34,7 +34,7 @@ RSpec.describe CanvasSync do
34
34
  expect(chain.chain_data).to eq({
35
35
  jobs: [
36
36
  { job: CanvasSync::Jobs::SyncTermsJob.to_s, options: { a: 1 } },
37
- { job: CanvasSync::Jobs::SyncUsersJob.to_s, options: { b: 2 } },
37
+ { job: CanvasSync::Jobs::SyncProvisioningReportJob.to_s, options: { models: ['users'], b: 2 } },
38
38
  { job: CanvasSync::Jobs::SyncProvisioningReportJob.to_s, options: { term_scope: 'active', models: ['courses'], c: 3 } }
39
39
  ],
40
40
  global_options: { legacy_support: false, d: 4 }
@@ -47,7 +47,7 @@ RSpec.describe CanvasSync do
47
47
  expect(chain.chain_data).to eq({
48
48
  jobs: [
49
49
  { job: CanvasSync::Jobs::SyncTermsJob.to_s, options: {} },
50
- { job: CanvasSync::Jobs::SyncUsersJob.to_s, options: {} },
50
+ { job: CanvasSync::Jobs::SyncProvisioningReportJob.to_s, options: { models: ['users'] } },
51
51
  { job: CanvasSync::Jobs::SyncProvisioningReportJob.to_s, options: { term_scope: 'active', models: ['courses'] } }
52
52
  ],
53
53
  global_options: { legacy_support: false }
@@ -247,4 +247,7 @@ RSpec.describe CanvasSync do
247
247
  end
248
248
  end
249
249
 
250
+ describe ".sync_scope" do
251
+
252
+ end
250
253
  end
@@ -8,4 +8,7 @@ RSpec.describe Account, type: :model do
8
8
  it { should validate_uniqueness_of(:canvas_id) }
9
9
  end
10
10
 
11
+ describe 'associations' do
12
+ it { should have_many(:groups) }
13
+ end
11
14
  end
@@ -41,5 +41,9 @@ RSpec.describe Course, type: :model do
41
41
  it do
42
42
  should have_many(:submissions)
43
43
  end
44
+
45
+ it do
46
+ should have_many(:groups)
47
+ end
44
48
  end
45
49
  end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe GroupMembership, type: :model do
4
+ let(:subject) {
5
+ FactoryGirl.create(:group_membership, group: FactoryGirl.create(:group), user: FactoryGirl.create(:user))
6
+ }
7
+
8
+ describe 'validations' do
9
+ it { should validate_presence_of(:canvas_id) }
10
+ it { should validate_uniqueness_of(:canvas_id) }
11
+ end
12
+
13
+ describe 'associations' do
14
+ it do
15
+ should belong_to(:group)
16
+ .with_primary_key(:canvas_id)
17
+ .with_foreign_key(:canvas_group_id)
18
+ end
19
+
20
+ it do
21
+ should belong_to(:user)
22
+ .with_primary_key(:canvas_id)
23
+ .with_foreign_key(:canvas_user_id)
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Group, type: :model do
4
+ let(:subject) { FactoryGirl.create(:group) }
5
+
6
+ describe 'validations' do
7
+ it { should validate_presence_of(:canvas_id) }
8
+ it { should validate_uniqueness_of(:canvas_id) }
9
+ end
10
+
11
+ describe 'associations' do
12
+ it { should have_many(:group_memberships) }
13
+
14
+ it do
15
+ should belong_to(:course)
16
+ .with_primary_key(:canvas_id)
17
+ .with_foreign_key(:canvas_course_id)
18
+ end
19
+
20
+ it do
21
+ should belong_to(:account)
22
+ .with_primary_key(:canvas_id)
23
+ .with_foreign_key(:canvas_account_id)
24
+ end
25
+ end
26
+ end
@@ -9,6 +9,8 @@ RSpec.describe User, type: :model do
9
9
  end
10
10
 
11
11
  describe 'associations' do
12
+ it { should have_many(:group_memberships) }
13
+
12
14
  it do
13
15
  should have_many(:enrollments)
14
16
  .with_primary_key(:canvas_id)
@@ -42,6 +42,26 @@ RSpec.describe CanvasSync::Processors::ProvisioningReportProcessor do
42
42
  expect(cross_listed_section.canvas_nonxlist_course_id).to eq 2
43
43
  end
44
44
 
45
+ it 'processes groups' do
46
+ expect {
47
+ subject.process('spec/support/fixtures/reports/groups.csv', { models: ['groups'] }, 1)
48
+ }.to change { Group.count }.by(2)
49
+ group = Group.find_by_name('Group1')
50
+ expect(group.workflow_state).to eq 'available'
51
+ expect(group.canvas_account_id).to eq 1
52
+ expect(group.canvas_id).to eq 50
53
+ end
54
+
55
+ it 'processes group memberships' do
56
+ expect {
57
+ subject.process('spec/support/fixtures/reports/group_memberships.csv', { models: ['group_membership'] }, 1)
58
+ }.to change { GroupMembership.count }.by(2)
59
+ group = GroupMembership.find_by_canvas_id(50)
60
+ expect(group.workflow_state).to eq 'accepted'
61
+ expect(group.canvas_group_id).to eq 1
62
+ expect(group.canvas_user_id).to eq 10
63
+ end
64
+
45
65
  context 'options[:models] is multiple models' do
46
66
  it 'extracts the ZIP and processes each model' do
47
67
  user_count = User.count
@@ -18,6 +18,7 @@ class Account < ApplicationRecord
18
18
  primary_key: :canvas_id, foreign_key: :canvas_parent_account_id
19
19
  has_many :sub_accounts, class_name: 'Account',
20
20
  primary_key: :canvas_id, foreign_key: :canvas_parent_account_id
21
+ has_many :groups, primary_key: :canvas_id, foreign_key: :canvas_account_id
21
22
 
22
23
  api_syncable({
23
24
  name: :name,
@@ -17,6 +17,7 @@ class Course < ApplicationRecord
17
17
  has_many :assignments, as: :context, primary_key: :canvas_id, foreign_key: :canvas_context_id, foreign_type: :canvas_context_type
18
18
  has_many :submissions, primary_key: :canvas_id, foreign_key: :canvas_course_id
19
19
  has_many :assignment_groups, primary_key: :canvas_id, foreign_key: :canvas_course_id
20
+ has_many :groups, primary_key: :canvas_id, foreign_key: :canvas_course_id
20
21
 
21
22
  api_syncable({
22
23
  sis_id: :sis_course_id,
@@ -0,0 +1,25 @@
1
+ # #
2
+ # AUTO GENERATED MODEL
3
+ # This model was auto generated by the CanvasSync Gem.
4
+ # You can customize it as needed, but make sure you test
5
+ # any changes you make to the auto generated methods.
6
+ #
7
+
8
+
9
+ class Group < ApplicationRecord
10
+ include CanvasSync::Record
11
+ include CanvasSync::Concerns::ApiSyncable
12
+
13
+ validates :canvas_id, uniqueness: true, presence: true
14
+ belongs_to :course, primary_key: :canvas_id, foreign_key: :canvas_course_id, optional: true
15
+ belongs_to :account, primary_key: :canvas_id, foreign_key: :canvas_account_id, optional: true
16
+ has_many :group_memberships, primary_key: :canvas_id, foreign_key: :canvas_group_id
17
+
18
+ api_syncable({
19
+ canvas_id: :id,
20
+ name: :name,
21
+ canvas_course_id: :course_id,
22
+ sis_id: :sis_group_id,
23
+ workflow_state: ->(r){ 'available' },
24
+ }, -> (api) { api.group(canvas_id) })
25
+ end
@@ -0,0 +1,23 @@
1
+ # #
2
+ # AUTO GENERATED MODEL
3
+ # This model was auto generated by the CanvasSync Gem.
4
+ # You can customize it as needed, but make sure you test
5
+ # any changes you make to the auto generated methods.
6
+ #
7
+
8
+
9
+ class GroupMembership < ApplicationRecord
10
+ include CanvasSync::Record
11
+ include CanvasSync::Concerns::ApiSyncable
12
+
13
+ validates :canvas_id, uniqueness: true, presence: true
14
+ belongs_to :group, primary_key: :canvas_id, foreign_key: :canvas_group_id
15
+ belongs_to :user, primary_key: :canvas_id, foreign_key: :canvas_user_id
16
+
17
+ api_syncable({
18
+ canvas_id: :id,
19
+ canvas_group_id: :group_id,
20
+ canvas_user_id: :user_id,
21
+ workflow_state: :workflow_state,
22
+ }, -> (api) { api.group_membership(canvas_group_id, canvas_id) })
23
+ end
@@ -15,6 +15,7 @@ class User < ApplicationRecord
15
15
  has_many :admins, primary_key: :canvas_id, foreign_key: :canvas_user_id
16
16
  has_many :admin_roles, through: :admins, source: :role
17
17
  has_many :submissions, primary_key: :canvas_id, foreign_key: :canvas_user_id
18
+ has_many :group_memberships, primary_key: :canvas_id, foreign_key: :canvas_user_id
18
19
 
19
20
  api_syncable({
20
21
  sis_id: :sis_user_id,
@@ -14,6 +14,7 @@ class CreateSubmissions < ActiveRecord::Migration[5.1]
14
14
  t.bigint :canvas_assignment_id
15
15
  t.bigint :canvas_user_id
16
16
  t.datetime :submitted_at
17
+ t.datetime :due_at
17
18
  t.datetime :graded_at
18
19
  t.float :score
19
20
  t.float :points_possible
@@ -0,0 +1,29 @@
1
+ # #
2
+ # AUTO GENERATED MIGRATION
3
+ # This migration was auto generated by the CanvasSync Gem.
4
+ # You can add new columns to this table, but removing or
5
+ # re-naming ones created here may break Canvas Syncing.
6
+ #
7
+
8
+
9
+ class CreateGroups < ActiveRecord::Migration[5.1]
10
+ def change
11
+ create_table :groups do |t|
12
+ t.bigint :canvas_id, null: false
13
+ t.string :sis_id
14
+ t.bigint :canvas_group_category_id
15
+ t.string :group_category_sis_id
16
+ t.bigint :canvas_account_id
17
+ t.bigint :canvas_course_id
18
+ t.string :name
19
+ t.string :workflow_state
20
+ t.bigint :context_id
21
+ t.string :context_type
22
+ t.integer :max_membership
23
+
24
+ t.timestamps
25
+ end
26
+
27
+ add_index :groups, :canvas_id, unique: true
28
+ end
29
+ end
@@ -0,0 +1,24 @@
1
+ # #
2
+ # AUTO GENERATED MIGRATION
3
+ # This migration was auto generated by the CanvasSync Gem.
4
+ # You can add new columns to this table, but removing or
5
+ # re-naming ones created here may break Canvas Syncing.
6
+ #
7
+
8
+
9
+ class CreateGroupMemberships < ActiveRecord::Migration[5.1]
10
+ def change
11
+ create_table :group_memberships do |t|
12
+ t.bigint :canvas_id, null: false
13
+ t.bigint :canvas_user_id, null: false
14
+ t.bigint :canvas_group_id, null: false
15
+ t.string :group_sis_id
16
+ t.string :user_sis_id
17
+ t.string :workflow_state
18
+
19
+ t.timestamps
20
+ end
21
+
22
+ add_index :group_memberships, :canvas_id, unique: true
23
+ end
24
+ end
@@ -10,7 +10,7 @@
10
10
  #
11
11
  # It's strongly recommended that you check this file into your version control system.
12
12
 
13
- ActiveRecord::Schema.define(version: 20190927204546) do
13
+ ActiveRecord::Schema.define(version: 2020_04_16_214248) do
14
14
 
15
15
  # These are extensions that must be enabled in order to support this database
16
16
  enable_extension "plpgsql"
@@ -162,6 +162,35 @@ ActiveRecord::Schema.define(version: 20190927204546) do
162
162
  t.index ["canvas_user_id"], name: "index_enrollments_on_canvas_user_id"
163
163
  end
164
164
 
165
+ create_table "group_memberships", force: :cascade do |t|
166
+ t.bigint "canvas_id", null: false
167
+ t.bigint "canvas_user_id", null: false
168
+ t.bigint "canvas_group_id", null: false
169
+ t.string "group_sis_id"
170
+ t.string "user_sis_id"
171
+ t.string "workflow_state"
172
+ t.datetime "created_at", null: false
173
+ t.datetime "updated_at", null: false
174
+ t.index ["canvas_id"], name: "index_group_memberships_on_canvas_id", unique: true
175
+ end
176
+
177
+ create_table "groups", force: :cascade do |t|
178
+ t.bigint "canvas_id", null: false
179
+ t.string "sis_id"
180
+ t.bigint "canvas_group_category_id"
181
+ t.string "group_category_sis_id"
182
+ t.bigint "canvas_account_id"
183
+ t.bigint "canvas_course_id"
184
+ t.string "name"
185
+ t.string "workflow_state"
186
+ t.bigint "context_id"
187
+ t.string "context_type"
188
+ t.integer "max_membership"
189
+ t.datetime "created_at", null: false
190
+ t.datetime "updated_at", null: false
191
+ t.index ["canvas_id"], name: "index_groups_on_canvas_id", unique: true
192
+ end
193
+
165
194
  create_table "roles", force: :cascade do |t|
166
195
  t.integer "canvas_id", null: false
167
196
  t.string "label"
@@ -196,6 +225,7 @@ ActiveRecord::Schema.define(version: 20190927204546) do
196
225
  t.bigint "canvas_assignment_id"
197
226
  t.bigint "canvas_user_id"
198
227
  t.datetime "submitted_at"
228
+ t.datetime "due_at"
199
229
  t.datetime "graded_at"
200
230
  t.float "score"
201
231
  t.float "points_possible"
@@ -0,0 +1,8 @@
1
+ FactoryGirl.define do
2
+ factory :group do
3
+ canvas_id { SecureRandom.random_number(100_000_000) }
4
+ sis_id { SecureRandom.hex }
5
+ name 'Some User Group'
6
+ workflow_state 'available'
7
+ end
8
+ end
@@ -0,0 +1,6 @@
1
+ FactoryGirl.define do
2
+ factory :group_membership do
3
+ canvas_id { SecureRandom.random_number(100_000_000) }
4
+ workflow_state 'accepted'
5
+ end
6
+ end
@@ -0,0 +1,3 @@
1
+ canvas_group_id,group_id,canvas_user_id,user_id,status,created_by_sis,canvas_group_membership_id
2
+ 1,,10,,accepted,false,50
3
+ 2,,11,,accepted,false,51
@@ -0,0 +1,3 @@
1
+ canvas_group_id,group_id,canvas_group_category_id,group_category_id,canvas_account_id,account_id,canvas_course_id,course_id,name,status,created_by_sis,context_id,context_type,max_membership
2
+ 50,sis1,10,,1,,,,Group1,available,false,1,Account,
3
+ 51,sis2,2,,,,1,coursesis,Group2,available,false,1,Course,1
@@ -1,3 +1,3 @@
1
- "canvas user id","sis user id","user name","canvas course id","sis course id","course name","assignment id","assignment name","submission date","graded date","score","points possible","submission id","workflow state","excused"
2
- 1,1,userName,1,1,courseName,1,assignmentName,2017-09-21 18:28:15 UTC,2017-09-21 19:36:23 UTC,5,10,1,graded,true
3
- 1,1,userName,1,1,courseName,2,assignment2Name,2017-09-21 18:28:15 UTC,2017-09-21 19:36:23 UTC,5,10,2,submitted,false
1
+ "canvas user id","sis user id","user name","canvas course id","sis course id","course name","assignment id","assignment name","submission date","graded date","score","points possible","submission id","workflow state","excused","due at"
2
+ 1,1,userName,1,1,courseName,1,assignmentName,2017-09-21 18:28:15 UTC,2017-09-21 19:36:23 UTC,5,10,1,graded,true,2017-09-27 18:28:15 UTC
3
+ 1,1,userName,1,1,courseName,2,assignment2Name,2017-09-21 18:28:15 UTC,2017-09-21 19:36:23 UTC,5,10,2,submitted,false,2017-09-28 18:28:15 UTC
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: canvas_sync
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.13.0
4
+ version: 0.16.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nate Collings
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-03-04 00:00:00.000000000 Z
11
+ date: 2020-09-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -304,7 +304,7 @@ dependencies:
304
304
  - - ">="
305
305
  - !ruby/object:Gem::Version
306
306
  version: '0'
307
- description:
307
+ description:
308
308
  email:
309
309
  - ncollings@instructure.com
310
310
  executables: []
@@ -338,6 +338,9 @@ files:
338
338
  - lib/canvas_sync/generators/templates/migrations/create_context_modules.rb
339
339
  - lib/canvas_sync/generators/templates/migrations/create_courses.rb
340
340
  - lib/canvas_sync/generators/templates/migrations/create_enrollments.rb
341
+ - lib/canvas_sync/generators/templates/migrations/create_group_memberships.rb
342
+ - lib/canvas_sync/generators/templates/migrations/create_groups.rb
343
+ - lib/canvas_sync/generators/templates/migrations/create_pseudonyms.rb
341
344
  - lib/canvas_sync/generators/templates/migrations/create_roles.rb
342
345
  - lib/canvas_sync/generators/templates/migrations/create_sections.rb
343
346
  - lib/canvas_sync/generators/templates/migrations/create_submissions.rb
@@ -351,6 +354,9 @@ files:
351
354
  - lib/canvas_sync/generators/templates/models/context_module_item.rb
352
355
  - lib/canvas_sync/generators/templates/models/course.rb
353
356
  - lib/canvas_sync/generators/templates/models/enrollment.rb
357
+ - lib/canvas_sync/generators/templates/models/group.rb
358
+ - lib/canvas_sync/generators/templates/models/group_membership.rb
359
+ - lib/canvas_sync/generators/templates/models/pseudonym.rb
354
360
  - lib/canvas_sync/generators/templates/models/role.rb
355
361
  - lib/canvas_sync/generators/templates/models/section.rb
356
362
  - lib/canvas_sync/generators/templates/models/submission.rb
@@ -387,7 +393,6 @@ files:
387
393
  - lib/canvas_sync/jobs/sync_simple_table_job.rb
388
394
  - lib/canvas_sync/jobs/sync_submissions_job.rb
389
395
  - lib/canvas_sync/jobs/sync_terms_job.rb
390
- - lib/canvas_sync/jobs/sync_users_job.rb
391
396
  - lib/canvas_sync/processors/assignment_groups_processor.rb
392
397
  - lib/canvas_sync/processors/assignments_processor.rb
393
398
  - lib/canvas_sync/processors/context_module_items_processor.rb
@@ -416,7 +421,6 @@ files:
416
421
  - spec/canvas_sync/jobs/sync_simple_table_job_spec.rb
417
422
  - spec/canvas_sync/jobs/sync_submissions_job_spec.rb
418
423
  - spec/canvas_sync/jobs/sync_terms_job_spec.rb
419
- - spec/canvas_sync/jobs/sync_users_job_spec.rb
420
424
  - spec/canvas_sync/models/accounts_spec.rb
421
425
  - spec/canvas_sync/models/admins_spec.rb
422
426
  - spec/canvas_sync/models/assignment_group_spec.rb
@@ -425,6 +429,8 @@ files:
425
429
  - spec/canvas_sync/models/context_module_spec.rb
426
430
  - spec/canvas_sync/models/course_spec.rb
427
431
  - spec/canvas_sync/models/enrollment_spec.rb
432
+ - spec/canvas_sync/models/group_membership_spec.rb
433
+ - spec/canvas_sync/models/group_spec.rb
428
434
  - spec/canvas_sync/models/roles_spec.rb
429
435
  - spec/canvas_sync/models/section_spec.rb
430
436
  - spec/canvas_sync/models/submission_spec.rb
@@ -450,6 +456,8 @@ files:
450
456
  - spec/dummy/app/models/context_module_item.rb
451
457
  - spec/dummy/app/models/course.rb
452
458
  - spec/dummy/app/models/enrollment.rb
459
+ - spec/dummy/app/models/group.rb
460
+ - spec/dummy/app/models/group_membership.rb
453
461
  - spec/dummy/app/models/role.rb
454
462
  - spec/dummy/app/models/section.rb
455
463
  - spec/dummy/app/models/submission.rb
@@ -510,6 +518,8 @@ files:
510
518
  - spec/dummy/db/migrate/20190702203632_create_context_module_items.rb
511
519
  - spec/dummy/db/migrate/20190927204545_create_roles.rb
512
520
  - spec/dummy/db/migrate/20190927204546_create_admins.rb
521
+ - spec/dummy/db/migrate/20200415171620_create_groups.rb
522
+ - spec/dummy/db/migrate/20200416214248_create_group_memberships.rb
513
523
  - spec/dummy/db/schema.rb
514
524
  - spec/dummy/db/test.sqlite3
515
525
  - spec/dummy/log/development.log
@@ -522,6 +532,8 @@ files:
522
532
  - spec/factories/context_module_item_factory.rb
523
533
  - spec/factories/course_factory.rb
524
534
  - spec/factories/enrollment_factory.rb
535
+ - spec/factories/group_factory.rb
536
+ - spec/factories/group_membership_factory.rb
525
537
  - spec/factories/role_factory.rb
526
538
  - spec/factories/section_factory.rb
527
539
  - spec/factories/submission_factory.rb
@@ -540,6 +552,8 @@ files:
540
552
  - spec/support/fixtures/reports/context_modules.csv
541
553
  - spec/support/fixtures/reports/courses.csv
542
554
  - spec/support/fixtures/reports/enrollments.csv
555
+ - spec/support/fixtures/reports/group_memberships.csv
556
+ - spec/support/fixtures/reports/groups.csv
543
557
  - spec/support/fixtures/reports/provisioning_csv
544
558
  - spec/support/fixtures/reports/provisioning_csv_unzipped/courses.csv
545
559
  - spec/support/fixtures/reports/provisioning_csv_unzipped/users.csv
@@ -550,7 +564,7 @@ files:
550
564
  homepage: https://instructure.com
551
565
  licenses: []
552
566
  metadata: {}
553
- post_install_message:
567
+ post_install_message:
554
568
  rdoc_options: []
555
569
  require_paths:
556
570
  - lib
@@ -565,8 +579,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
565
579
  - !ruby/object:Gem::Version
566
580
  version: '0'
567
581
  requirements: []
568
- rubygems_version: 3.0.3
569
- signing_key:
582
+ rubygems_version: 3.1.2
583
+ signing_key:
570
584
  specification_version: 4
571
585
  summary: Gem for generating Canvas models and migrations and syncing data from Canvas
572
586
  test_files:
@@ -586,7 +600,6 @@ test_files:
586
600
  - spec/canvas_sync/jobs/sync_simple_table_job_spec.rb
587
601
  - spec/canvas_sync/jobs/sync_submissions_job_spec.rb
588
602
  - spec/canvas_sync/jobs/sync_terms_job_spec.rb
589
- - spec/canvas_sync/jobs/sync_users_job_spec.rb
590
603
  - spec/canvas_sync/models/accounts_spec.rb
591
604
  - spec/canvas_sync/models/admins_spec.rb
592
605
  - spec/canvas_sync/models/assignment_group_spec.rb
@@ -595,6 +608,8 @@ test_files:
595
608
  - spec/canvas_sync/models/context_module_spec.rb
596
609
  - spec/canvas_sync/models/course_spec.rb
597
610
  - spec/canvas_sync/models/enrollment_spec.rb
611
+ - spec/canvas_sync/models/group_membership_spec.rb
612
+ - spec/canvas_sync/models/group_spec.rb
598
613
  - spec/canvas_sync/models/roles_spec.rb
599
614
  - spec/canvas_sync/models/section_spec.rb
600
615
  - spec/canvas_sync/models/submission_spec.rb
@@ -620,6 +635,8 @@ test_files:
620
635
  - spec/dummy/app/models/context_module_item.rb
621
636
  - spec/dummy/app/models/course.rb
622
637
  - spec/dummy/app/models/enrollment.rb
638
+ - spec/dummy/app/models/group.rb
639
+ - spec/dummy/app/models/group_membership.rb
623
640
  - spec/dummy/app/models/role.rb
624
641
  - spec/dummy/app/models/section.rb
625
642
  - spec/dummy/app/models/submission.rb
@@ -680,6 +697,8 @@ test_files:
680
697
  - spec/dummy/db/migrate/20190702203632_create_context_module_items.rb
681
698
  - spec/dummy/db/migrate/20190927204545_create_roles.rb
682
699
  - spec/dummy/db/migrate/20190927204546_create_admins.rb
700
+ - spec/dummy/db/migrate/20200415171620_create_groups.rb
701
+ - spec/dummy/db/migrate/20200416214248_create_group_memberships.rb
683
702
  - spec/dummy/db/schema.rb
684
703
  - spec/dummy/db/test.sqlite3
685
704
  - spec/dummy/log/development.log
@@ -692,6 +711,8 @@ test_files:
692
711
  - spec/factories/context_module_item_factory.rb
693
712
  - spec/factories/course_factory.rb
694
713
  - spec/factories/enrollment_factory.rb
714
+ - spec/factories/group_factory.rb
715
+ - spec/factories/group_membership_factory.rb
695
716
  - spec/factories/role_factory.rb
696
717
  - spec/factories/section_factory.rb
697
718
  - spec/factories/submission_factory.rb
@@ -710,6 +731,8 @@ test_files:
710
731
  - spec/support/fixtures/reports/context_modules.csv
711
732
  - spec/support/fixtures/reports/courses.csv
712
733
  - spec/support/fixtures/reports/enrollments.csv
734
+ - spec/support/fixtures/reports/group_memberships.csv
735
+ - spec/support/fixtures/reports/groups.csv
713
736
  - spec/support/fixtures/reports/provisioning_csv
714
737
  - spec/support/fixtures/reports/provisioning_csv_unzipped/courses.csv
715
738
  - spec/support/fixtures/reports/provisioning_csv_unzipped/users.csv
@@ -1,26 +0,0 @@
1
- module CanvasSync
2
- module Jobs
3
- class SyncUsersJob < ReportStarter
4
- # Starts a provisioning report for just users.
5
- #
6
- # Provisioning reports do not scope users by term, so when we are
7
- # running provisioning by term we sync users first so we don't duplicate
8
- # the work of syncing all users for each term.
9
- #
10
- # @param job_chain [Hash]
11
- # @param options [Hash]
12
- def perform(job_chain, options)
13
- super(
14
- job_chain,
15
- "proservices_provisioning_csv",
16
- merge_report_params(job_chain, options, {
17
- users: true,
18
- include_deleted: true,
19
- }, term_scope: false),
20
- CanvasSync::Processors::ProvisioningReportProcessor.to_s,
21
- { models: ["users"] },
22
- )
23
- end
24
- end
25
- end
26
- end
@@ -1,15 +0,0 @@
1
- require 'spec_helper'
2
-
3
- RSpec.describe CanvasSync::Jobs::SyncUsersJob do
4
- describe '#perform' do
5
- it 'enqueues a ReportStarter for a provisioning report across all terms with just users' do
6
- expect_any_instance_of(Bearcat::Client).to receive(:start_report)
7
- .with('self', 'proservices_provisioning_csv', { parameters: { users: true, include_deleted: true } })
8
- .and_return({ 'id' => 1 })
9
-
10
- expect(CanvasSync::Jobs::ReportChecker).to receive(:set).and_call_original
11
-
12
- CanvasSync::Jobs::SyncUsersJob.perform_now({ jobs: [], global_options: {}}, {})
13
- end
14
- end
15
- end