@happyvertical/smrt-education 0.57.40 → 0.57.41

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.
@@ -4,8 +4,8 @@ import { AssetCollection, createAssetRuntime, withPrivateAssetAccess } from "@ha
4
4
  import { TenantCollection } from "@happyvertical/smrt-users";
5
5
  //#region \0rolldown/runtime.js
6
6
  var __create = Object.create;
7
- var __defProp$7 = Object.defineProperty;
8
- var __getOwnPropDesc$7 = Object.getOwnPropertyDescriptor;
7
+ var __defProp$8 = Object.defineProperty;
8
+ var __getOwnPropDesc$8 = Object.getOwnPropertyDescriptor;
9
9
  var __getOwnPropNames = Object.getOwnPropertyNames;
10
10
  var __getProtoOf = Object.getPrototypeOf;
11
11
  var __hasOwnProp = Object.prototype.hasOwnProperty;
@@ -13,34 +13,34 @@ var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).expor
13
13
  var __copyProps = (to, from, except, desc) => {
14
14
  if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
15
15
  key = keys[i];
16
- if (!__hasOwnProp.call(to, key) && key !== except) __defProp$7(to, key, {
16
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp$8(to, key, {
17
17
  get: ((k) => from[k]).bind(null, key),
18
- enumerable: !(desc = __getOwnPropDesc$7(from, key)) || desc.enumerable
18
+ enumerable: !(desc = __getOwnPropDesc$8(from, key)) || desc.enumerable
19
19
  });
20
20
  }
21
21
  return to;
22
22
  };
23
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp$7(target, "default", {
23
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp$8(target, "default", {
24
24
  value: mod,
25
25
  enumerable: true
26
26
  }) : target, mod));
27
27
  //#endregion
28
28
  //#region src/catalog.ts
29
- var __defProp$6 = Object.defineProperty;
30
- var __getOwnPropDesc$6 = Object.getOwnPropertyDescriptor;
31
- var __defNormalProp$6 = (obj, key, value) => key in obj ? __defProp$6(obj, key, {
29
+ var __defProp$7 = Object.defineProperty;
30
+ var __getOwnPropDesc$7 = Object.getOwnPropertyDescriptor;
31
+ var __defNormalProp$7 = (obj, key, value) => key in obj ? __defProp$7(obj, key, {
32
32
  enumerable: true,
33
33
  configurable: true,
34
34
  writable: true,
35
35
  value
36
36
  }) : obj[key] = value;
37
- var __decorateClass$6 = (decorators, target, key, kind) => {
38
- var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$6(target, key) : target;
37
+ var __decorateClass$7 = (decorators, target, key, kind) => {
38
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$7(target, key) : target;
39
39
  for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
40
- if (kind && result) __defProp$6(target, key, result);
40
+ if (kind && result) __defProp$7(target, key, result);
41
41
  return result;
42
42
  };
43
- var __publicField$6 = (obj, key, value) => __defNormalProp$6(obj, typeof key !== "symbol" ? key + "" : key, value);
43
+ var __publicField$7 = (obj, key, value) => __defNormalProp$7(obj, typeof key !== "symbol" ? key + "" : key, value);
44
44
  var closed$5 = {
45
45
  api: false,
46
46
  mcp: false,
@@ -100,22 +100,22 @@ var Course = class extends SmrtObject {
100
100
  return await super.save(options);
101
101
  }
102
102
  };
103
- __publicField$6(Course, "__smrtPackage__", "@happyvertical/smrt-education");
104
- __decorateClass$6([tenantId({ nullable: true })], Course.prototype, "tenantId", 2);
105
- __decorateClass$6([field({ required: true })], Course.prototype, "title", 2);
106
- Course = __decorateClass$6([TenantScoped({ mode: "optional" }), smrt({
103
+ __publicField$7(Course, "__smrtPackage__", "@happyvertical/smrt-education");
104
+ __decorateClass$7([tenantId({ nullable: true })], Course.prototype, "tenantId", 2);
105
+ __decorateClass$7([field({ required: true })], Course.prototype, "title", 2);
106
+ Course = __decorateClass$7([TenantScoped({ mode: "optional" }), smrt({
107
107
  tableStrategy: "sti",
108
108
  ...closed$5
109
109
  })], Course);
110
110
  var ExternalCourse = class extends Course {};
111
- __publicField$6(ExternalCourse, "__smrtPackage__", "@happyvertical/smrt-education");
112
- ExternalCourse = __decorateClass$6([smrt({
111
+ __publicField$7(ExternalCourse, "__smrtPackage__", "@happyvertical/smrt-education");
112
+ ExternalCourse = __decorateClass$7([smrt({
113
113
  tableName: "courses",
114
114
  ...closed$5
115
115
  })], ExternalCourse);
116
116
  var AuthoredCourse = class extends Course {};
117
- __publicField$6(AuthoredCourse, "__smrtPackage__", "@happyvertical/smrt-education");
118
- AuthoredCourse = __decorateClass$6([smrt({
117
+ __publicField$7(AuthoredCourse, "__smrtPackage__", "@happyvertical/smrt-education");
118
+ AuthoredCourse = __decorateClass$7([smrt({
119
119
  tableName: "courses",
120
120
  ...closed$5
121
121
  })], AuthoredCourse);
@@ -138,11 +138,11 @@ var CourseSection = class extends SmrtObject {
138
138
  return await super.save(options);
139
139
  }
140
140
  };
141
- __publicField$6(CourseSection, "__smrtPackage__", "@happyvertical/smrt-education");
142
- __decorateClass$6([tenantId({ nullable: true })], CourseSection.prototype, "tenantId", 2);
143
- __decorateClass$6([foreignKey("Course", { required: true })], CourseSection.prototype, "courseId", 2);
144
- __decorateClass$6([field({ required: true })], CourseSection.prototype, "title", 2);
145
- CourseSection = __decorateClass$6([TenantScoped({ mode: "optional" }), smrt({ ...closed$5 })], CourseSection);
141
+ __publicField$7(CourseSection, "__smrtPackage__", "@happyvertical/smrt-education");
142
+ __decorateClass$7([tenantId({ nullable: true })], CourseSection.prototype, "tenantId", 2);
143
+ __decorateClass$7([foreignKey("Course", { required: true })], CourseSection.prototype, "courseId", 2);
144
+ __decorateClass$7([field({ required: true })], CourseSection.prototype, "title", 2);
145
+ CourseSection = __decorateClass$7([TenantScoped({ mode: "optional" }), smrt({ ...closed$5 })], CourseSection);
146
146
  var Lesson = class extends SmrtObject {
147
147
  tenantId = null;
148
148
  sectionId = "";
@@ -169,17 +169,17 @@ var Lesson = class extends SmrtObject {
169
169
  return await super.save(options);
170
170
  }
171
171
  };
172
- __publicField$6(Lesson, "__smrtPackage__", "@happyvertical/smrt-education");
173
- __decorateClass$6([tenantId({ nullable: true })], Lesson.prototype, "tenantId", 2);
174
- __decorateClass$6([foreignKey("CourseSection", { required: true })], Lesson.prototype, "sectionId", 2);
175
- __decorateClass$6([field({ required: true })], Lesson.prototype, "title", 2);
176
- Lesson = __decorateClass$6([TenantScoped({ mode: "optional" }), smrt({
172
+ __publicField$7(Lesson, "__smrtPackage__", "@happyvertical/smrt-education");
173
+ __decorateClass$7([tenantId({ nullable: true })], Lesson.prototype, "tenantId", 2);
174
+ __decorateClass$7([foreignKey("CourseSection", { required: true })], Lesson.prototype, "sectionId", 2);
175
+ __decorateClass$7([field({ required: true })], Lesson.prototype, "title", 2);
176
+ Lesson = __decorateClass$7([TenantScoped({ mode: "optional" }), smrt({
177
177
  tableStrategy: "sti",
178
178
  ...closed$5
179
179
  })], Lesson);
180
180
  var Reading = class extends Lesson {};
181
- __publicField$6(Reading, "__smrtPackage__", "@happyvertical/smrt-education");
182
- Reading = __decorateClass$6([smrt({
181
+ __publicField$7(Reading, "__smrtPackage__", "@happyvertical/smrt-education");
182
+ Reading = __decorateClass$7([smrt({
183
183
  tableName: "lessons",
184
184
  ...closed$5
185
185
  })], Reading);
@@ -190,8 +190,8 @@ var Video = class extends Lesson {
190
190
  applyModelOptions(this, options);
191
191
  }
192
192
  };
193
- __publicField$6(Video, "__smrtPackage__", "@happyvertical/smrt-education");
194
- Video = __decorateClass$6([smrt({
193
+ __publicField$7(Video, "__smrtPackage__", "@happyvertical/smrt-education");
194
+ Video = __decorateClass$7([smrt({
195
195
  tableName: "lessons",
196
196
  ...closed$5
197
197
  })], Video);
@@ -205,14 +205,14 @@ var Worksheet = class extends Lesson {
205
205
  applyModelOptions(this, options);
206
206
  }
207
207
  };
208
- __publicField$6(Worksheet, "__smrtPackage__", "@happyvertical/smrt-education");
209
- Worksheet = __decorateClass$6([smrt({
208
+ __publicField$7(Worksheet, "__smrtPackage__", "@happyvertical/smrt-education");
209
+ Worksheet = __decorateClass$7([smrt({
210
210
  tableName: "lessons",
211
211
  ...closed$5
212
212
  })], Worksheet);
213
213
  var Exercise = class extends Lesson {};
214
- __publicField$6(Exercise, "__smrtPackage__", "@happyvertical/smrt-education");
215
- Exercise = __decorateClass$6([smrt({
214
+ __publicField$7(Exercise, "__smrtPackage__", "@happyvertical/smrt-education");
215
+ Exercise = __decorateClass$7([smrt({
216
216
  tableName: "lessons",
217
217
  ...closed$5
218
218
  })], Exercise);
@@ -246,21 +246,21 @@ GlobalInterceptors.register({
246
246
  });
247
247
  //#endregion
248
248
  //#region src/learners.ts
249
- var __defProp$5 = Object.defineProperty;
250
- var __getOwnPropDesc$5 = Object.getOwnPropertyDescriptor;
251
- var __defNormalProp$5 = (obj, key, value) => key in obj ? __defProp$5(obj, key, {
249
+ var __defProp$6 = Object.defineProperty;
250
+ var __getOwnPropDesc$6 = Object.getOwnPropertyDescriptor;
251
+ var __defNormalProp$6 = (obj, key, value) => key in obj ? __defProp$6(obj, key, {
252
252
  enumerable: true,
253
253
  configurable: true,
254
254
  writable: true,
255
255
  value
256
256
  }) : obj[key] = value;
257
- var __decorateClass$5 = (decorators, target, key, kind) => {
258
- var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$5(target, key) : target;
257
+ var __decorateClass$6 = (decorators, target, key, kind) => {
258
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$6(target, key) : target;
259
259
  for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
260
- if (kind && result) __defProp$5(target, key, result);
260
+ if (kind && result) __defProp$6(target, key, result);
261
261
  return result;
262
262
  };
263
- var __publicField$5 = (obj, key, value) => __defNormalProp$5(obj, typeof key !== "symbol" ? key + "" : key, value);
263
+ var __publicField$6 = (obj, key, value) => __defNormalProp$6(obj, typeof key !== "symbol" ? key + "" : key, value);
264
264
  var closed$4 = {
265
265
  api: false,
266
266
  mcp: false,
@@ -326,11 +326,11 @@ var Learner = class extends SmrtObject {
326
326
  return super.save(options);
327
327
  }
328
328
  };
329
- __publicField$5(Learner, "__smrtPackage__", "@happyvertical/smrt-education");
330
- __decorateClass$5([tenantId()], Learner.prototype, "tenantId", 2);
331
- __decorateClass$5([crossPackageRef("@happyvertical/smrt-users:User", { required: true })], Learner.prototype, "userId", 2);
332
- __decorateClass$5([crossPackageRef("@happyvertical/smrt-profiles:Profile", { required: true })], Learner.prototype, "profileId", 2);
333
- Learner = __decorateClass$5([TenantScoped({ mode: "required" }), smrt({ ...closed$4 })], Learner);
329
+ __publicField$6(Learner, "__smrtPackage__", "@happyvertical/smrt-education");
330
+ __decorateClass$6([tenantId()], Learner.prototype, "tenantId", 2);
331
+ __decorateClass$6([crossPackageRef("@happyvertical/smrt-users:User", { required: true })], Learner.prototype, "userId", 2);
332
+ __decorateClass$6([crossPackageRef("@happyvertical/smrt-profiles:Profile", { required: true })], Learner.prototype, "profileId", 2);
333
+ Learner = __decorateClass$6([TenantScoped({ mode: "required" }), smrt({ ...closed$4 })], Learner);
334
334
  var Curriculum = class extends SmrtObject {
335
335
  tenantId = "";
336
336
  learnerId = "";
@@ -357,11 +357,11 @@ var Curriculum = class extends SmrtObject {
357
357
  return super.save(options);
358
358
  }
359
359
  };
360
- __publicField$5(Curriculum, "__smrtPackage__", "@happyvertical/smrt-education");
361
- __decorateClass$5([tenantId()], Curriculum.prototype, "tenantId", 2);
362
- __decorateClass$5([foreignKey("Learner", { required: true })], Curriculum.prototype, "learnerId", 2);
363
- __decorateClass$5([field({ required: true })], Curriculum.prototype, "title", 2);
364
- Curriculum = __decorateClass$5([TenantScoped({ mode: "required" }), smrt({
360
+ __publicField$6(Curriculum, "__smrtPackage__", "@happyvertical/smrt-education");
361
+ __decorateClass$6([tenantId()], Curriculum.prototype, "tenantId", 2);
362
+ __decorateClass$6([foreignKey("Learner", { required: true })], Curriculum.prototype, "learnerId", 2);
363
+ __decorateClass$6([field({ required: true })], Curriculum.prototype, "title", 2);
364
+ Curriculum = __decorateClass$6([TenantScoped({ mode: "required" }), smrt({
365
365
  ...closed$4,
366
366
  tableName: "curricula"
367
367
  })], Curriculum);
@@ -401,12 +401,12 @@ var Enrollment = class extends SmrtObject {
401
401
  return super.save(options);
402
402
  }
403
403
  };
404
- __publicField$5(Enrollment, "__smrtPackage__", "@happyvertical/smrt-education");
405
- __decorateClass$5([tenantId()], Enrollment.prototype, "tenantId", 2);
406
- __decorateClass$5([foreignKey("Curriculum", { required: true })], Enrollment.prototype, "curriculumId", 2);
407
- __decorateClass$5([foreignKey("Learner", { required: true })], Enrollment.prototype, "learnerId", 2);
408
- __decorateClass$5([foreignKey("Course", { required: true })], Enrollment.prototype, "courseId", 2);
409
- Enrollment = __decorateClass$5([TenantScoped({ mode: "required" }), smrt({
404
+ __publicField$6(Enrollment, "__smrtPackage__", "@happyvertical/smrt-education");
405
+ __decorateClass$6([tenantId()], Enrollment.prototype, "tenantId", 2);
406
+ __decorateClass$6([foreignKey("Curriculum", { required: true })], Enrollment.prototype, "curriculumId", 2);
407
+ __decorateClass$6([foreignKey("Learner", { required: true })], Enrollment.prototype, "learnerId", 2);
408
+ __decorateClass$6([foreignKey("Course", { required: true })], Enrollment.prototype, "courseId", 2);
409
+ Enrollment = __decorateClass$6([TenantScoped({ mode: "required" }), smrt({
410
410
  ...closed$4,
411
411
  conflictColumns: [
412
412
  "tenant_id",
@@ -458,16 +458,16 @@ var LessonProgress = class extends SmrtObject {
458
458
  return super.save(options);
459
459
  }
460
460
  };
461
- __publicField$5(LessonProgress, "__smrtPackage__", "@happyvertical/smrt-education");
462
- __decorateClass$5([tenantId()], LessonProgress.prototype, "tenantId", 2);
463
- __decorateClass$5([foreignKey("Enrollment", { required: true })], LessonProgress.prototype, "enrollmentId", 2);
464
- __decorateClass$5([foreignKey("Learner", { required: true })], LessonProgress.prototype, "learnerId", 2);
465
- __decorateClass$5([foreignKey("Lesson", { required: true })], LessonProgress.prototype, "lessonId", 2);
466
- __decorateClass$5([field({
461
+ __publicField$6(LessonProgress, "__smrtPackage__", "@happyvertical/smrt-education");
462
+ __decorateClass$6([tenantId()], LessonProgress.prototype, "tenantId", 2);
463
+ __decorateClass$6([foreignKey("Enrollment", { required: true })], LessonProgress.prototype, "enrollmentId", 2);
464
+ __decorateClass$6([foreignKey("Learner", { required: true })], LessonProgress.prototype, "learnerId", 2);
465
+ __decorateClass$6([foreignKey("Lesson", { required: true })], LessonProgress.prototype, "lessonId", 2);
466
+ __decorateClass$6([field({
467
467
  type: "decimal",
468
468
  nullable: true
469
469
  })], LessonProgress.prototype, "bestScore", 2);
470
- LessonProgress = __decorateClass$5([TenantScoped({ mode: "required" }), smrt({
470
+ LessonProgress = __decorateClass$6([TenantScoped({ mode: "required" }), smrt({
471
471
  ...closed$4,
472
472
  tableName: "lesson_progress",
473
473
  conflictColumns: [
@@ -478,21 +478,21 @@ LessonProgress = __decorateClass$5([TenantScoped({ mode: "required" }), smrt({
478
478
  })], LessonProgress);
479
479
  //#endregion
480
480
  //#region src/lesson-assets.ts
481
- var __defProp$4 = Object.defineProperty;
482
- var __getOwnPropDesc$4 = Object.getOwnPropertyDescriptor;
483
- var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, {
481
+ var __defProp$5 = Object.defineProperty;
482
+ var __getOwnPropDesc$5 = Object.getOwnPropertyDescriptor;
483
+ var __defNormalProp$5 = (obj, key, value) => key in obj ? __defProp$5(obj, key, {
484
484
  enumerable: true,
485
485
  configurable: true,
486
486
  writable: true,
487
487
  value
488
488
  }) : obj[key] = value;
489
- var __decorateClass$4 = (decorators, target, key, kind) => {
490
- var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$4(target, key) : target;
489
+ var __decorateClass$5 = (decorators, target, key, kind) => {
490
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$5(target, key) : target;
491
491
  for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
492
- if (kind && result) __defProp$4(target, key, result);
492
+ if (kind && result) __defProp$5(target, key, result);
493
493
  return result;
494
494
  };
495
- var __publicField$4 = (obj, key, value) => __defNormalProp$4(obj, typeof key !== "symbol" ? key + "" : key, value);
495
+ var __publicField$5 = (obj, key, value) => __defNormalProp$5(obj, typeof key !== "symbol" ? key + "" : key, value);
496
496
  var LessonAsset = class extends SmrtObject {
497
497
  tenantId = null;
498
498
  lessonId = "";
@@ -526,12 +526,12 @@ var LessonAsset = class extends SmrtObject {
526
526
  return await super.save(options);
527
527
  }
528
528
  };
529
- __publicField$4(LessonAsset, "__smrtPackage__", "@happyvertical/smrt-education");
530
- __decorateClass$4([tenantId({ nullable: true })], LessonAsset.prototype, "tenantId", 2);
531
- __decorateClass$4([foreignKey("Lesson", { required: true })], LessonAsset.prototype, "lessonId", 2);
532
- __decorateClass$4([crossPackageRef("@happyvertical/smrt-assets:Asset", { required: true })], LessonAsset.prototype, "assetId", 2);
533
- __decorateClass$4([field({ required: true })], LessonAsset.prototype, "relationship", 2);
534
- LessonAsset = __decorateClass$4([TenantScoped({ mode: "optional" }), smrt({
529
+ __publicField$5(LessonAsset, "__smrtPackage__", "@happyvertical/smrt-education");
530
+ __decorateClass$5([tenantId({ nullable: true })], LessonAsset.prototype, "tenantId", 2);
531
+ __decorateClass$5([foreignKey("Lesson", { required: true })], LessonAsset.prototype, "lessonId", 2);
532
+ __decorateClass$5([crossPackageRef("@happyvertical/smrt-assets:Asset", { required: true })], LessonAsset.prototype, "assetId", 2);
533
+ __decorateClass$5([field({ required: true })], LessonAsset.prototype, "relationship", 2);
534
+ LessonAsset = __decorateClass$5([TenantScoped({ mode: "optional" }), smrt({
535
535
  tableName: "lesson_assets",
536
536
  conflictColumns: [
537
537
  "tenant_id",
@@ -545,21 +545,21 @@ LessonAsset = __decorateClass$4([TenantScoped({ mode: "optional" }), smrt({
545
545
  })], LessonAsset);
546
546
  //#endregion
547
547
  //#region src/submissions.ts
548
- var __defProp$3 = Object.defineProperty;
549
- var __getOwnPropDesc$3 = Object.getOwnPropertyDescriptor;
550
- var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, {
548
+ var __defProp$4 = Object.defineProperty;
549
+ var __getOwnPropDesc$4 = Object.getOwnPropertyDescriptor;
550
+ var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, {
551
551
  enumerable: true,
552
552
  configurable: true,
553
553
  writable: true,
554
554
  value
555
555
  }) : obj[key] = value;
556
- var __decorateClass$3 = (decorators, target, key, kind) => {
557
- var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$3(target, key) : target;
556
+ var __decorateClass$4 = (decorators, target, key, kind) => {
557
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$4(target, key) : target;
558
558
  for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
559
- if (kind && result) __defProp$3(target, key, result);
559
+ if (kind && result) __defProp$4(target, key, result);
560
560
  return result;
561
561
  };
562
- var __publicField$3 = (obj, key, value) => __defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value);
562
+ var __publicField$4 = (obj, key, value) => __defNormalProp$4(obj, typeof key !== "symbol" ? key + "" : key, value);
563
563
  var closed$3 = {
564
564
  api: false,
565
565
  mcp: false,
@@ -650,18 +650,18 @@ var Submission = class extends SmrtObject {
650
650
  return super.save(options);
651
651
  }
652
652
  };
653
- __publicField$3(Submission, "__smrtPackage__", "@happyvertical/smrt-education");
654
- __decorateClass$3([tenantId()], Submission.prototype, "tenantId", 2);
655
- __decorateClass$3([foreignKey("Learner", { required: true })], Submission.prototype, "learnerId", 2);
656
- __decorateClass$3([foreignKey("Lesson", { required: true })], Submission.prototype, "lessonId", 2);
657
- __decorateClass$3([foreignKey("LessonProgress", { required: true })], Submission.prototype, "progressId", 2);
658
- __decorateClass$3([field({ required: true })], Submission.prototype, "kind", 2);
659
- __decorateClass$3([foreignKey("Submission", { nullable: true })], Submission.prototype, "previousSubmissionId", 2);
660
- __decorateClass$3([field({
653
+ __publicField$4(Submission, "__smrtPackage__", "@happyvertical/smrt-education");
654
+ __decorateClass$4([tenantId()], Submission.prototype, "tenantId", 2);
655
+ __decorateClass$4([foreignKey("Learner", { required: true })], Submission.prototype, "learnerId", 2);
656
+ __decorateClass$4([foreignKey("Lesson", { required: true })], Submission.prototype, "lessonId", 2);
657
+ __decorateClass$4([foreignKey("LessonProgress", { required: true })], Submission.prototype, "progressId", 2);
658
+ __decorateClass$4([field({ required: true })], Submission.prototype, "kind", 2);
659
+ __decorateClass$4([foreignKey("Submission", { nullable: true })], Submission.prototype, "previousSubmissionId", 2);
660
+ __decorateClass$4([field({
661
661
  type: "text",
662
662
  nullable: true
663
663
  })], Submission.prototype, "intakeItemId", 2);
664
- Submission = __decorateClass$3([TenantScoped({ mode: "required" }), smrt({
664
+ Submission = __decorateClass$4([TenantScoped({ mode: "required" }), smrt({
665
665
  tableStrategy: "sti",
666
666
  ...closed$3
667
667
  })], Submission);
@@ -684,14 +684,14 @@ var SubmissionIntakeBinding = class extends SmrtObject {
684
684
  return super.save(options);
685
685
  }
686
686
  };
687
- __publicField$3(SubmissionIntakeBinding, "__smrtPackage__", "@happyvertical/smrt-education");
688
- __decorateClass$3([tenantId()], SubmissionIntakeBinding.prototype, "tenantId", 2);
689
- __decorateClass$3([field({
687
+ __publicField$4(SubmissionIntakeBinding, "__smrtPackage__", "@happyvertical/smrt-education");
688
+ __decorateClass$4([tenantId()], SubmissionIntakeBinding.prototype, "tenantId", 2);
689
+ __decorateClass$4([field({
690
690
  required: true,
691
691
  type: "text"
692
692
  })], SubmissionIntakeBinding.prototype, "intakeItemId", 2);
693
- __decorateClass$3([foreignKey("Submission", { required: true })], SubmissionIntakeBinding.prototype, "submissionId", 2);
694
- SubmissionIntakeBinding = __decorateClass$3([TenantScoped({ mode: "required" }), smrt({
693
+ __decorateClass$4([foreignKey("Submission", { required: true })], SubmissionIntakeBinding.prototype, "submissionId", 2);
694
+ SubmissionIntakeBinding = __decorateClass$4([TenantScoped({ mode: "required" }), smrt({
695
695
  tableName: "submission_intake_bindings",
696
696
  ...closed$3,
697
697
  conflictColumns: ["tenant_id", "intake_item_id"]
@@ -715,8 +715,8 @@ var ScannedSubmission = class extends Submission {
715
715
  return super.save(options);
716
716
  }
717
717
  };
718
- __publicField$3(ScannedSubmission, "__smrtPackage__", "@happyvertical/smrt-education");
719
- ScannedSubmission = __decorateClass$3([smrt({
718
+ __publicField$4(ScannedSubmission, "__smrtPackage__", "@happyvertical/smrt-education");
719
+ ScannedSubmission = __decorateClass$4([smrt({
720
720
  tableName: "submissions",
721
721
  ...closed$3
722
722
  })], ScannedSubmission);
@@ -738,15 +738,15 @@ var ExternalCompletion = class extends Submission {
738
738
  return super.save(options);
739
739
  }
740
740
  };
741
- __publicField$3(ExternalCompletion, "__smrtPackage__", "@happyvertical/smrt-education");
742
- __decorateClass$3([field({ type: "decimal" })], ExternalCompletion.prototype, "reportedScore", 2);
743
- ExternalCompletion = __decorateClass$3([smrt({
741
+ __publicField$4(ExternalCompletion, "__smrtPackage__", "@happyvertical/smrt-education");
742
+ __decorateClass$4([field({ type: "decimal" })], ExternalCompletion.prototype, "reportedScore", 2);
743
+ ExternalCompletion = __decorateClass$4([smrt({
744
744
  tableName: "submissions",
745
745
  ...closed$3
746
746
  })], ExternalCompletion);
747
747
  var Attestation = class extends Submission {};
748
- __publicField$3(Attestation, "__smrtPackage__", "@happyvertical/smrt-education");
749
- Attestation = __decorateClass$3([smrt({
748
+ __publicField$4(Attestation, "__smrtPackage__", "@happyvertical/smrt-education");
749
+ Attestation = __decorateClass$4([smrt({
750
750
  tableName: "submissions",
751
751
  ...closed$3
752
752
  })], Attestation);
@@ -785,12 +785,12 @@ var SubmissionAsset = class extends SmrtObject {
785
785
  return super.save(options);
786
786
  }
787
787
  };
788
- __publicField$3(SubmissionAsset, "__smrtPackage__", "@happyvertical/smrt-education");
789
- __decorateClass$3([tenantId()], SubmissionAsset.prototype, "tenantId", 2);
790
- __decorateClass$3([foreignKey("Submission", { required: true })], SubmissionAsset.prototype, "submissionId", 2);
791
- __decorateClass$3([crossPackageRef("@happyvertical/smrt-assets:Asset", { required: true })], SubmissionAsset.prototype, "assetId", 2);
792
- __decorateClass$3([field({ required: true })], SubmissionAsset.prototype, "relationship", 2);
793
- SubmissionAsset = __decorateClass$3([TenantScoped({ mode: "required" }), smrt({
788
+ __publicField$4(SubmissionAsset, "__smrtPackage__", "@happyvertical/smrt-education");
789
+ __decorateClass$4([tenantId()], SubmissionAsset.prototype, "tenantId", 2);
790
+ __decorateClass$4([foreignKey("Submission", { required: true })], SubmissionAsset.prototype, "submissionId", 2);
791
+ __decorateClass$4([crossPackageRef("@happyvertical/smrt-assets:Asset", { required: true })], SubmissionAsset.prototype, "assetId", 2);
792
+ __decorateClass$4([field({ required: true })], SubmissionAsset.prototype, "relationship", 2);
793
+ SubmissionAsset = __decorateClass$4([TenantScoped({ mode: "required" }), smrt({
794
794
  tableName: "submission_assets",
795
795
  conflictColumns: [
796
796
  "tenant_id",
@@ -839,24 +839,24 @@ var Grade = class extends SmrtObject {
839
839
  return super.save(options);
840
840
  }
841
841
  };
842
- __publicField$3(Grade, "__smrtPackage__", "@happyvertical/smrt-education");
843
- __decorateClass$3([tenantId()], Grade.prototype, "tenantId", 2);
844
- __decorateClass$3([foreignKey("Submission", { required: true })], Grade.prototype, "submissionId", 2);
845
- __decorateClass$3([field({ required: true })], Grade.prototype, "graderKind", 2);
846
- __decorateClass$3([crossPackageRef("@happyvertical/smrt-profiles:Profile", { nullable: true })], Grade.prototype, "graderProfileId", 2);
847
- __decorateClass$3([field({
842
+ __publicField$4(Grade, "__smrtPackage__", "@happyvertical/smrt-education");
843
+ __decorateClass$4([tenantId()], Grade.prototype, "tenantId", 2);
844
+ __decorateClass$4([foreignKey("Submission", { required: true })], Grade.prototype, "submissionId", 2);
845
+ __decorateClass$4([field({ required: true })], Grade.prototype, "graderKind", 2);
846
+ __decorateClass$4([crossPackageRef("@happyvertical/smrt-profiles:Profile", { nullable: true })], Grade.prototype, "graderProfileId", 2);
847
+ __decorateClass$4([field({
848
848
  type: "decimal",
849
849
  nullable: true
850
850
  })], Grade.prototype, "score", 2);
851
- __decorateClass$3([field({
851
+ __decorateClass$4([field({
852
852
  type: "integer",
853
853
  nullable: true
854
854
  })], Grade.prototype, "pointsEarned", 2);
855
- __decorateClass$3([field({
855
+ __decorateClass$4([field({
856
856
  type: "integer",
857
857
  nullable: true
858
858
  })], Grade.prototype, "pointsPossible", 2);
859
- Grade = __decorateClass$3([TenantScoped({ mode: "required" }), smrt({ ...closed$3 })], Grade);
859
+ Grade = __decorateClass$4([TenantScoped({ mode: "required" }), smrt({ ...closed$3 })], Grade);
860
860
  //#endregion
861
861
  //#region src/collections.ts
862
862
  var CourseCollection = class extends SmrtCollection {
@@ -1059,21 +1059,21 @@ function familyIntakeScopeId(tenantId) {
1059
1059
  }
1060
1060
  //#endregion
1061
1061
  //#region src/family-intake-models.ts
1062
- var __defProp$2 = Object.defineProperty;
1063
- var __getOwnPropDesc$2 = Object.getOwnPropertyDescriptor;
1064
- var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, {
1062
+ var __defProp$3 = Object.defineProperty;
1063
+ var __getOwnPropDesc$3 = Object.getOwnPropertyDescriptor;
1064
+ var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, {
1065
1065
  enumerable: true,
1066
1066
  configurable: true,
1067
1067
  writable: true,
1068
1068
  value
1069
1069
  }) : obj[key] = value;
1070
- var __decorateClass$2 = (decorators, target, key, kind) => {
1071
- var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$2(target, key) : target;
1070
+ var __decorateClass$3 = (decorators, target, key, kind) => {
1071
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$3(target, key) : target;
1072
1072
  for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
1073
- if (kind && result) __defProp$2(target, key, result);
1073
+ if (kind && result) __defProp$3(target, key, result);
1074
1074
  return result;
1075
1075
  };
1076
- var __publicField$2 = (obj, key, value) => __defNormalProp$2(obj, typeof key !== "symbol" ? key + "" : key, value);
1076
+ var __publicField$3 = (obj, key, value) => __defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value);
1077
1077
  var closed$2 = {
1078
1078
  api: false,
1079
1079
  mcp: false,
@@ -1104,11 +1104,11 @@ var FamilyIntake = class extends SmrtObject {
1104
1104
  noDelete();
1105
1105
  }
1106
1106
  };
1107
- __publicField$2(FamilyIntake, "__smrtPackage__", "@happyvertical/smrt-education");
1108
- __decorateClass$2([tenantId()], FamilyIntake.prototype, "tenantId", 2);
1109
- __decorateClass$2([crossPackageRef("@happyvertical/smrt-profiles:Profile")], FamilyIntake.prototype, "ownerProfileId", 2);
1110
- __decorateClass$2([field({ type: "text" })], FamilyIntake.prototype, "sourceJson", 2);
1111
- FamilyIntake = __decorateClass$2([TenantScoped({ mode: "required" }), smrt({
1107
+ __publicField$3(FamilyIntake, "__smrtPackage__", "@happyvertical/smrt-education");
1108
+ __decorateClass$3([tenantId()], FamilyIntake.prototype, "tenantId", 2);
1109
+ __decorateClass$3([crossPackageRef("@happyvertical/smrt-profiles:Profile")], FamilyIntake.prototype, "ownerProfileId", 2);
1110
+ __decorateClass$3([field({ type: "text" })], FamilyIntake.prototype, "sourceJson", 2);
1111
+ FamilyIntake = __decorateClass$3([TenantScoped({ mode: "required" }), smrt({
1112
1112
  tableName: "family_intakes",
1113
1113
  conflictColumns: ["tenant_id", "item_id"],
1114
1114
  ...closed$2
@@ -1146,11 +1146,11 @@ var FamilyIntakeAsset = class extends SmrtObject {
1146
1146
  noDelete();
1147
1147
  }
1148
1148
  };
1149
- __publicField$2(FamilyIntakeAsset, "__smrtPackage__", "@happyvertical/smrt-education");
1150
- __decorateClass$2([tenantId()], FamilyIntakeAsset.prototype, "tenantId", 2);
1151
- __decorateClass$2([foreignKey("FamilyIntake", { required: true })], FamilyIntakeAsset.prototype, "intakeId", 2);
1152
- __decorateClass$2([crossPackageRef("@happyvertical/smrt-assets:Asset")], FamilyIntakeAsset.prototype, "assetId", 2);
1153
- FamilyIntakeAsset = __decorateClass$2([TenantScoped({ mode: "required" }), smrt({
1149
+ __publicField$3(FamilyIntakeAsset, "__smrtPackage__", "@happyvertical/smrt-education");
1150
+ __decorateClass$3([tenantId()], FamilyIntakeAsset.prototype, "tenantId", 2);
1151
+ __decorateClass$3([foreignKey("FamilyIntake", { required: true })], FamilyIntakeAsset.prototype, "intakeId", 2);
1152
+ __decorateClass$3([crossPackageRef("@happyvertical/smrt-assets:Asset")], FamilyIntakeAsset.prototype, "assetId", 2);
1153
+ FamilyIntakeAsset = __decorateClass$3([TenantScoped({ mode: "required" }), smrt({
1154
1154
  tableName: "family_intake_assets",
1155
1155
  conflictColumns: [
1156
1156
  "tenant_id",
@@ -1185,11 +1185,11 @@ var FamilyIntakeDecision = class extends SmrtObject {
1185
1185
  noDelete();
1186
1186
  }
1187
1187
  };
1188
- __publicField$2(FamilyIntakeDecision, "__smrtPackage__", "@happyvertical/smrt-education");
1189
- __decorateClass$2([tenantId()], FamilyIntakeDecision.prototype, "tenantId", 2);
1190
- __decorateClass$2([foreignKey("FamilyIntake", { required: true })], FamilyIntakeDecision.prototype, "intakeId", 2);
1191
- __decorateClass$2([field({ type: "text" })], FamilyIntakeDecision.prototype, "bodyJson", 2);
1192
- FamilyIntakeDecision = __decorateClass$2([TenantScoped({ mode: "required" }), smrt({
1188
+ __publicField$3(FamilyIntakeDecision, "__smrtPackage__", "@happyvertical/smrt-education");
1189
+ __decorateClass$3([tenantId()], FamilyIntakeDecision.prototype, "tenantId", 2);
1190
+ __decorateClass$3([foreignKey("FamilyIntake", { required: true })], FamilyIntakeDecision.prototype, "intakeId", 2);
1191
+ __decorateClass$3([field({ type: "text" })], FamilyIntakeDecision.prototype, "bodyJson", 2);
1192
+ FamilyIntakeDecision = __decorateClass$3([TenantScoped({ mode: "required" }), smrt({
1193
1193
  tableName: "family_intake_decisions",
1194
1194
  conflictColumns: [
1195
1195
  "tenant_id",
@@ -1251,6 +1251,14 @@ function aggregateWorkbookQuestions(questions) {
1251
1251
  function workbookAggregateFeedback(aggregate) {
1252
1252
  return `${aggregate.correct} correct; ${aggregate.incorrect} incorrect; ${aggregate.partiallyCorrect} partially correct; ${aggregate.unassessed} unassessed.`;
1253
1253
  }
1254
+ var WorkbookCompletionConflictError = class extends Error {
1255
+ constructor(code) {
1256
+ super(`Workbook completion conflict: ${code}`);
1257
+ this.code = code;
1258
+ this.name = "WorkbookCompletionConflictError";
1259
+ }
1260
+ code;
1261
+ };
1254
1262
  function text(value, label, max = 1e4) {
1255
1263
  if (typeof value !== "string" || value.length > max) throw new WorkbookAssessmentValidationError(`Invalid ${label}`);
1256
1264
  }
@@ -1363,21 +1371,21 @@ var WORKBOOK_MATH_VOCABULARY = {
1363
1371
  };
1364
1372
  //#endregion
1365
1373
  //#region src/workbook-models.ts
1366
- var __defProp$1 = Object.defineProperty;
1367
- var __getOwnPropDesc$1 = Object.getOwnPropertyDescriptor;
1368
- var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, {
1374
+ var __defProp$2 = Object.defineProperty;
1375
+ var __getOwnPropDesc$2 = Object.getOwnPropertyDescriptor;
1376
+ var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, {
1369
1377
  enumerable: true,
1370
1378
  configurable: true,
1371
1379
  writable: true,
1372
1380
  value
1373
1381
  }) : obj[key] = value;
1374
- var __decorateClass$1 = (decorators, target, key, kind) => {
1375
- var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$1(target, key) : target;
1382
+ var __decorateClass$2 = (decorators, target, key, kind) => {
1383
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$2(target, key) : target;
1376
1384
  for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
1377
- if (kind && result) __defProp$1(target, key, result);
1385
+ if (kind && result) __defProp$2(target, key, result);
1378
1386
  return result;
1379
1387
  };
1380
- var __publicField$1 = (obj, key, value) => __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
1388
+ var __publicField$2 = (obj, key, value) => __defNormalProp$2(obj, typeof key !== "symbol" ? key + "" : key, value);
1381
1389
  var closed$1 = {
1382
1390
  api: false,
1383
1391
  mcp: false,
@@ -1416,10 +1424,10 @@ var Workbook = class extends SmrtObject {
1416
1424
  return super.save(options);
1417
1425
  }
1418
1426
  };
1419
- __publicField$1(Workbook, "__smrtPackage__", "@happyvertical/smrt-education");
1420
- __decorateClass$1([tenantId()], Workbook.prototype, "tenantId", 2);
1421
- __decorateClass$1([foreignKey("Learner", { required: true })], Workbook.prototype, "learnerId", 2);
1422
- Workbook = __decorateClass$1([TenantScoped({ mode: "required" }), smrt({
1427
+ __publicField$2(Workbook, "__smrtPackage__", "@happyvertical/smrt-education");
1428
+ __decorateClass$2([tenantId()], Workbook.prototype, "tenantId", 2);
1429
+ __decorateClass$2([foreignKey("Learner", { required: true })], Workbook.prototype, "learnerId", 2);
1430
+ Workbook = __decorateClass$2([TenantScoped({ mode: "required" }), smrt({
1423
1431
  tableName: "workbooks",
1424
1432
  conflictColumns: [
1425
1433
  "tenant_id",
@@ -1497,19 +1505,19 @@ var WorkbookActivity = class extends SmrtObject {
1497
1505
  return super.save(options);
1498
1506
  }
1499
1507
  };
1500
- __publicField$1(WorkbookActivity, "__smrtPackage__", "@happyvertical/smrt-education");
1501
- __decorateClass$1([tenantId()], WorkbookActivity.prototype, "tenantId", 2);
1502
- __decorateClass$1([foreignKey("Learner", { required: true })], WorkbookActivity.prototype, "learnerId", 2);
1503
- __decorateClass$1([foreignKey("Workbook", { nullable: true })], WorkbookActivity.prototype, "workbookId", 2);
1504
- __decorateClass$1([field({
1508
+ __publicField$2(WorkbookActivity, "__smrtPackage__", "@happyvertical/smrt-education");
1509
+ __decorateClass$2([tenantId()], WorkbookActivity.prototype, "tenantId", 2);
1510
+ __decorateClass$2([foreignKey("Learner", { required: true })], WorkbookActivity.prototype, "learnerId", 2);
1511
+ __decorateClass$2([foreignKey("Workbook", { nullable: true })], WorkbookActivity.prototype, "workbookId", 2);
1512
+ __decorateClass$2([field({
1505
1513
  type: "text",
1506
1514
  required: true,
1507
1515
  default: "identified"
1508
1516
  })], WorkbookActivity.prototype, "captureKind", 2);
1509
- __decorateClass$1([foreignKey("WorkbookPhotoIntake", { nullable: true })], WorkbookActivity.prototype, "photoIntakeId", 2);
1510
- __decorateClass$1([foreignKey("Enrollment", { required: true })], WorkbookActivity.prototype, "enrollmentId", 2);
1511
- __decorateClass$1([foreignKey("Lesson", { required: true })], WorkbookActivity.prototype, "lessonId", 2);
1512
- WorkbookActivity = __decorateClass$1([TenantScoped({ mode: "required" }), smrt({
1517
+ __decorateClass$2([foreignKey("WorkbookPhotoIntake", { nullable: true })], WorkbookActivity.prototype, "photoIntakeId", 2);
1518
+ __decorateClass$2([foreignKey("Enrollment", { required: true })], WorkbookActivity.prototype, "enrollmentId", 2);
1519
+ __decorateClass$2([foreignKey("Lesson", { required: true })], WorkbookActivity.prototype, "lessonId", 2);
1520
+ WorkbookActivity = __decorateClass$2([TenantScoped({ mode: "required" }), smrt({
1513
1521
  tableName: "workbook_activities",
1514
1522
  conflictColumns: [
1515
1523
  "tenant_id",
@@ -1573,14 +1581,14 @@ var WorkbookWorkFiling = class extends SmrtObject {
1573
1581
  return super.save(options);
1574
1582
  }
1575
1583
  };
1576
- __publicField$1(WorkbookWorkFiling, "__smrtPackage__", "@happyvertical/smrt-education");
1577
- __decorateClass$1([tenantId()], WorkbookWorkFiling.prototype, "tenantId", 2);
1578
- __decorateClass$1([foreignKey("Learner", { required: true })], WorkbookWorkFiling.prototype, "learnerId", 2);
1579
- __decorateClass$1([foreignKey("WorkbookActivity", { required: true })], WorkbookWorkFiling.prototype, "sourceActivityId", 2);
1580
- __decorateClass$1([foreignKey("Workbook", { required: true })], WorkbookWorkFiling.prototype, "workbookId", 2);
1581
- __decorateClass$1([foreignKey("WorkbookActivity", { nullable: true })], WorkbookWorkFiling.prototype, "canonicalActivityId", 2);
1582
- __decorateClass$1([foreignKey("WorkbookWorkFiling", { nullable: true })], WorkbookWorkFiling.prototype, "previousRevisionId", 2);
1583
- WorkbookWorkFiling = __decorateClass$1([TenantScoped({ mode: "required" }), smrt({
1584
+ __publicField$2(WorkbookWorkFiling, "__smrtPackage__", "@happyvertical/smrt-education");
1585
+ __decorateClass$2([tenantId()], WorkbookWorkFiling.prototype, "tenantId", 2);
1586
+ __decorateClass$2([foreignKey("Learner", { required: true })], WorkbookWorkFiling.prototype, "learnerId", 2);
1587
+ __decorateClass$2([foreignKey("WorkbookActivity", { required: true })], WorkbookWorkFiling.prototype, "sourceActivityId", 2);
1588
+ __decorateClass$2([foreignKey("Workbook", { required: true })], WorkbookWorkFiling.prototype, "workbookId", 2);
1589
+ __decorateClass$2([foreignKey("WorkbookActivity", { nullable: true })], WorkbookWorkFiling.prototype, "canonicalActivityId", 2);
1590
+ __decorateClass$2([foreignKey("WorkbookWorkFiling", { nullable: true })], WorkbookWorkFiling.prototype, "previousRevisionId", 2);
1591
+ WorkbookWorkFiling = __decorateClass$2([TenantScoped({ mode: "required" }), smrt({
1584
1592
  tableName: "workbook_work_filings",
1585
1593
  conflictColumns: [
1586
1594
  "tenant_id",
@@ -1647,14 +1655,14 @@ var WorkbookAttempt = class extends SmrtObject {
1647
1655
  return super.save(options);
1648
1656
  }
1649
1657
  };
1650
- __publicField$1(WorkbookAttempt, "__smrtPackage__", "@happyvertical/smrt-education");
1651
- __decorateClass$1([tenantId()], WorkbookAttempt.prototype, "tenantId", 2);
1652
- __decorateClass$1([foreignKey("Learner", { required: true })], WorkbookAttempt.prototype, "learnerId", 2);
1653
- __decorateClass$1([foreignKey("WorkbookActivity", { required: true })], WorkbookAttempt.prototype, "activityId", 2);
1654
- __decorateClass$1([foreignKey("Submission", { required: true })], WorkbookAttempt.prototype, "submissionId", 2);
1655
- __decorateClass$1([foreignKey("WorkbookAttempt", { nullable: true })], WorkbookAttempt.prototype, "previousAttemptId", 2);
1656
- __decorateClass$1([field({ type: "text" })], WorkbookAttempt.prototype, "sourceHashes", 2);
1657
- WorkbookAttempt = __decorateClass$1([TenantScoped({ mode: "required" }), smrt({
1658
+ __publicField$2(WorkbookAttempt, "__smrtPackage__", "@happyvertical/smrt-education");
1659
+ __decorateClass$2([tenantId()], WorkbookAttempt.prototype, "tenantId", 2);
1660
+ __decorateClass$2([foreignKey("Learner", { required: true })], WorkbookAttempt.prototype, "learnerId", 2);
1661
+ __decorateClass$2([foreignKey("WorkbookActivity", { required: true })], WorkbookAttempt.prototype, "activityId", 2);
1662
+ __decorateClass$2([foreignKey("Submission", { required: true })], WorkbookAttempt.prototype, "submissionId", 2);
1663
+ __decorateClass$2([foreignKey("WorkbookAttempt", { nullable: true })], WorkbookAttempt.prototype, "previousAttemptId", 2);
1664
+ __decorateClass$2([field({ type: "text" })], WorkbookAttempt.prototype, "sourceHashes", 2);
1665
+ WorkbookAttempt = __decorateClass$2([TenantScoped({ mode: "required" }), smrt({
1658
1666
  tableName: "workbook_attempts",
1659
1667
  conflictColumns: ["tenant_id", "submission_id"],
1660
1668
  ...closed$1
@@ -1701,14 +1709,14 @@ var WorkbookAssessmentRevision = class extends SmrtObject {
1701
1709
  return super.save(options);
1702
1710
  }
1703
1711
  };
1704
- __publicField$1(WorkbookAssessmentRevision, "__smrtPackage__", "@happyvertical/smrt-education");
1705
- __decorateClass$1([tenantId()], WorkbookAssessmentRevision.prototype, "tenantId", 2);
1706
- __decorateClass$1([foreignKey("Learner", { required: true })], WorkbookAssessmentRevision.prototype, "learnerId", 2);
1707
- __decorateClass$1([foreignKey("WorkbookAttempt", { required: true })], WorkbookAssessmentRevision.prototype, "attemptId", 2);
1708
- __decorateClass$1([foreignKey("WorkbookAssessmentRevision", { nullable: true })], WorkbookAssessmentRevision.prototype, "sourceRevisionId", 2);
1709
- __decorateClass$1([foreignKey("WorkbookAssessmentRevision", { nullable: true })], WorkbookAssessmentRevision.prototype, "supersedesId", 2);
1710
- __decorateClass$1([field({ type: "text" })], WorkbookAssessmentRevision.prototype, "assessmentJson", 2);
1711
- WorkbookAssessmentRevision = __decorateClass$1([TenantScoped({ mode: "required" }), smrt({
1712
+ __publicField$2(WorkbookAssessmentRevision, "__smrtPackage__", "@happyvertical/smrt-education");
1713
+ __decorateClass$2([tenantId()], WorkbookAssessmentRevision.prototype, "tenantId", 2);
1714
+ __decorateClass$2([foreignKey("Learner", { required: true })], WorkbookAssessmentRevision.prototype, "learnerId", 2);
1715
+ __decorateClass$2([foreignKey("WorkbookAttempt", { required: true })], WorkbookAssessmentRevision.prototype, "attemptId", 2);
1716
+ __decorateClass$2([foreignKey("WorkbookAssessmentRevision", { nullable: true })], WorkbookAssessmentRevision.prototype, "sourceRevisionId", 2);
1717
+ __decorateClass$2([foreignKey("WorkbookAssessmentRevision", { nullable: true })], WorkbookAssessmentRevision.prototype, "supersedesId", 2);
1718
+ __decorateClass$2([field({ type: "text" })], WorkbookAssessmentRevision.prototype, "assessmentJson", 2);
1719
+ WorkbookAssessmentRevision = __decorateClass$2([TenantScoped({ mode: "required" }), smrt({
1712
1720
  tableName: "workbook_assessment_revisions",
1713
1721
  conflictColumns: [
1714
1722
  "tenant_id",
@@ -1753,13 +1761,13 @@ var WorkbookFeedbackRelease = class extends SmrtObject {
1753
1761
  return super.save(options);
1754
1762
  }
1755
1763
  };
1756
- __publicField$1(WorkbookFeedbackRelease, "__smrtPackage__", "@happyvertical/smrt-education");
1757
- __decorateClass$1([tenantId()], WorkbookFeedbackRelease.prototype, "tenantId", 2);
1758
- __decorateClass$1([foreignKey("Learner", { required: true })], WorkbookFeedbackRelease.prototype, "learnerId", 2);
1759
- __decorateClass$1([foreignKey("WorkbookAttempt", { required: true })], WorkbookFeedbackRelease.prototype, "attemptId", 2);
1760
- __decorateClass$1([foreignKey("WorkbookAssessmentRevision", { required: true })], WorkbookFeedbackRelease.prototype, "revisionId", 2);
1761
- __decorateClass$1([foreignKey("WorkbookAssessmentRevision", { nullable: true })], WorkbookFeedbackRelease.prototype, "expectedHeadId", 2);
1762
- WorkbookFeedbackRelease = __decorateClass$1([TenantScoped({ mode: "required" }), smrt({
1764
+ __publicField$2(WorkbookFeedbackRelease, "__smrtPackage__", "@happyvertical/smrt-education");
1765
+ __decorateClass$2([tenantId()], WorkbookFeedbackRelease.prototype, "tenantId", 2);
1766
+ __decorateClass$2([foreignKey("Learner", { required: true })], WorkbookFeedbackRelease.prototype, "learnerId", 2);
1767
+ __decorateClass$2([foreignKey("WorkbookAttempt", { required: true })], WorkbookFeedbackRelease.prototype, "attemptId", 2);
1768
+ __decorateClass$2([foreignKey("WorkbookAssessmentRevision", { required: true })], WorkbookFeedbackRelease.prototype, "revisionId", 2);
1769
+ __decorateClass$2([foreignKey("WorkbookAssessmentRevision", { nullable: true })], WorkbookFeedbackRelease.prototype, "expectedHeadId", 2);
1770
+ WorkbookFeedbackRelease = __decorateClass$2([TenantScoped({ mode: "required" }), smrt({
1763
1771
  tableName: "workbook_feedback_releases",
1764
1772
  conflictColumns: [
1765
1773
  "tenant_id",
@@ -1802,12 +1810,12 @@ var WorkbookFeedbackDelivery = class extends SmrtObject {
1802
1810
  throw new Error("Workbook delivery history is immutable");
1803
1811
  }
1804
1812
  };
1805
- __publicField$1(WorkbookFeedbackDelivery, "__smrtPackage__", "@happyvertical/smrt-education");
1806
- __decorateClass$1([tenantId()], WorkbookFeedbackDelivery.prototype, "tenantId", 2);
1807
- __decorateClass$1([foreignKey("Learner", { required: true })], WorkbookFeedbackDelivery.prototype, "learnerId", 2);
1808
- __decorateClass$1([foreignKey("WorkbookAttempt", { required: true })], WorkbookFeedbackDelivery.prototype, "attemptId", 2);
1809
- __decorateClass$1([foreignKey("WorkbookAssessmentRevision", { required: true })], WorkbookFeedbackDelivery.prototype, "revisionId", 2);
1810
- WorkbookFeedbackDelivery = __decorateClass$1([TenantScoped({ mode: "required" }), smrt({
1813
+ __publicField$2(WorkbookFeedbackDelivery, "__smrtPackage__", "@happyvertical/smrt-education");
1814
+ __decorateClass$2([tenantId()], WorkbookFeedbackDelivery.prototype, "tenantId", 2);
1815
+ __decorateClass$2([foreignKey("Learner", { required: true })], WorkbookFeedbackDelivery.prototype, "learnerId", 2);
1816
+ __decorateClass$2([foreignKey("WorkbookAttempt", { required: true })], WorkbookFeedbackDelivery.prototype, "attemptId", 2);
1817
+ __decorateClass$2([foreignKey("WorkbookAssessmentRevision", { required: true })], WorkbookFeedbackDelivery.prototype, "revisionId", 2);
1818
+ WorkbookFeedbackDelivery = __decorateClass$2([TenantScoped({ mode: "required" }), smrt({
1811
1819
  tableName: "workbook_feedback_deliveries",
1812
1820
  conflictColumns: [
1813
1821
  "tenant_id",
@@ -1821,6 +1829,176 @@ var WorkbookFeedbackDeliveryCollection = class extends SmrtCollection {
1821
1829
  static _itemClass = WorkbookFeedbackDelivery;
1822
1830
  };
1823
1831
  //#endregion
1832
+ //#region src/workbook-completion.ts
1833
+ var __defProp$1 = Object.defineProperty;
1834
+ var __getOwnPropDesc$1 = Object.getOwnPropertyDescriptor;
1835
+ var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, {
1836
+ enumerable: true,
1837
+ configurable: true,
1838
+ writable: true,
1839
+ value
1840
+ }) : obj[key] = value;
1841
+ var __decorateClass$1 = (decorators, target, key, kind) => {
1842
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$1(target, key) : target;
1843
+ for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
1844
+ if (kind && result) __defProp$1(target, key, result);
1845
+ return result;
1846
+ };
1847
+ var __publicField$1 = (obj, key, value) => __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
1848
+ var WorkbookCompletionDecision = class extends SmrtObject {
1849
+ tenantId = "";
1850
+ learnerId = "";
1851
+ activityId = "";
1852
+ attemptId = "";
1853
+ submissionId = "";
1854
+ feedbackHeadId = null;
1855
+ actorUserId = "";
1856
+ requestKey = "";
1857
+ recordedAt = /* @__PURE__ */ new Date();
1858
+ constructor(options = {}) {
1859
+ super(options);
1860
+ for (const [key, value] of Object.entries(options)) if (Object.hasOwn(this, key)) this[key] = value;
1861
+ }
1862
+ async delete() {
1863
+ throw new Error("Workbook completion history is immutable");
1864
+ }
1865
+ async save(options) {
1866
+ if (this.id && await this.db.get(this.tableName, { id: this.id })) throw new Error("Workbook completion history is immutable");
1867
+ if (!this.tenantId.trim() || !this.actorUserId || typeof this.requestKey !== "string" || !this.requestKey.trim() || this.requestKey.length > 200 || Array.from(this.requestKey).some((character) => {
1868
+ const code = character.charCodeAt(0);
1869
+ return code < 32 || code === 127;
1870
+ })) throw new Error("Workbook completion requires tenant, actor and request key");
1871
+ const owner = {
1872
+ tenant_id: this.tenantId,
1873
+ learner_id: this.learnerId
1874
+ };
1875
+ const activity = await this.db.get("workbook_activities", {
1876
+ ...owner,
1877
+ id: this.activityId
1878
+ });
1879
+ const submission = await this.db.get("submissions", {
1880
+ ...owner,
1881
+ id: this.submissionId
1882
+ });
1883
+ if (!activity || !submission || !await this.db.get("learners", {
1884
+ id: this.learnerId,
1885
+ tenant_id: this.tenantId
1886
+ }) || !await this.db.get("workbook_attempts", {
1887
+ ...owner,
1888
+ id: this.attemptId,
1889
+ activity_id: this.activityId,
1890
+ submission_id: this.submissionId
1891
+ }) || submission.lesson_id !== activity.lesson_id || !await this.db.get("lesson_progress", {
1892
+ ...owner,
1893
+ id: submission.progress_id,
1894
+ enrollment_id: activity.enrollment_id,
1895
+ lesson_id: activity.lesson_id
1896
+ }) || !await this.db.get("memberships", {
1897
+ tenant_id: this.tenantId,
1898
+ user_id: this.actorUserId,
1899
+ status: "active"
1900
+ })) throw new Error("Workbook completion ownership mismatch");
1901
+ if (this.feedbackHeadId !== null && !await this.db.get("workbook_assessment_revisions", {
1902
+ ...owner,
1903
+ id: this.feedbackHeadId,
1904
+ attempt_id: this.attemptId
1905
+ })) throw new Error("Workbook completion feedback head mismatch");
1906
+ this.recordedAt = /* @__PURE__ */ new Date();
1907
+ this.requireInsertOnSave();
1908
+ return super.save(options);
1909
+ }
1910
+ };
1911
+ __publicField$1(WorkbookCompletionDecision, "__smrtPackage__", "@happyvertical/smrt-education");
1912
+ __decorateClass$1([tenantId()], WorkbookCompletionDecision.prototype, "tenantId", 2);
1913
+ __decorateClass$1([foreignKey("Learner", { required: true })], WorkbookCompletionDecision.prototype, "learnerId", 2);
1914
+ __decorateClass$1([foreignKey("WorkbookActivity", { required: true })], WorkbookCompletionDecision.prototype, "activityId", 2);
1915
+ __decorateClass$1([foreignKey("WorkbookAttempt", { required: true })], WorkbookCompletionDecision.prototype, "attemptId", 2);
1916
+ __decorateClass$1([foreignKey("Submission", { required: true })], WorkbookCompletionDecision.prototype, "submissionId", 2);
1917
+ __decorateClass$1([foreignKey("WorkbookAssessmentRevision", { nullable: true })], WorkbookCompletionDecision.prototype, "feedbackHeadId", 2);
1918
+ __decorateClass$1([crossPackageRef("@happyvertical/smrt-users:User", { required: true })], WorkbookCompletionDecision.prototype, "actorUserId", 2);
1919
+ WorkbookCompletionDecision = __decorateClass$1([TenantScoped({ mode: "required" }), smrt({
1920
+ api: false,
1921
+ mcp: false,
1922
+ cli: false,
1923
+ tableName: "workbook_completion_decisions",
1924
+ conflictColumns: [
1925
+ "tenant_id",
1926
+ "activity_id",
1927
+ "request_key"
1928
+ ],
1929
+ indexes: [{
1930
+ name: "workbook_completion_decisions_attempt_unique",
1931
+ columns: [
1932
+ "tenantId",
1933
+ "activityId",
1934
+ "attemptId"
1935
+ ],
1936
+ unique: true
1937
+ }]
1938
+ })], WorkbookCompletionDecision);
1939
+ var WorkbookCompletionDecisionCollection = class extends SmrtCollection {
1940
+ static _itemClass = WorkbookCompletionDecision;
1941
+ };
1942
+ async function readWorkbookCompletion(db, scope) {
1943
+ if (!scope.tenantId || !scope.learnerId || !scope.activityId) throw new Error("Workbook completion requires exact scope");
1944
+ const attempts = await db.tableExists("workbook_attempts") ? await (await WorkbookAttemptCollection.create({ db })).list({ where: scope }) : [];
1945
+ const byId = new Map(attempts.map((attempt) => [String(attempt.id), attempt]));
1946
+ const episodes = /* @__PURE__ */ new Map();
1947
+ for (const attempt of attempts) {
1948
+ const episode = episodes.get(attempt.episodeId) ?? [];
1949
+ episode.push(attempt);
1950
+ episodes.set(attempt.episodeId, episode);
1951
+ }
1952
+ const leaves = [];
1953
+ for (const episode of episodes.values()) {
1954
+ const predecessors = new Set(episode.flatMap((attempt) => attempt.previousAttemptId ? [attempt.previousAttemptId] : []));
1955
+ const episodeLeaves = episode.filter((attempt) => !predecessors.has(String(attempt.id)));
1956
+ if (episodeLeaves.length !== 1) throw new Error("Workbook current attempt is ambiguous");
1957
+ const leaf = episodeLeaves[0];
1958
+ const visited = /* @__PURE__ */ new Set();
1959
+ let ancestor = leaf;
1960
+ while (ancestor) {
1961
+ const id = String(ancestor.id);
1962
+ if (visited.has(id)) throw new Error("Workbook attempt ancestry is cyclic");
1963
+ if (ancestor.episodeId !== leaf.episodeId) throw new Error("Workbook attempt ancestry crosses practice episodes");
1964
+ visited.add(id);
1965
+ const previous = ancestor.previousAttemptId;
1966
+ ancestor = previous ? byId.get(previous) ?? null : null;
1967
+ if (previous && !ancestor) throw new Error("Workbook attempt ancestry is incomplete");
1968
+ }
1969
+ if (visited.size !== episode.length) throw new Error("Workbook attempt ancestry is disconnected");
1970
+ leaves.push(leaf);
1971
+ }
1972
+ leaves.sort((a, b) => new Date(b.capturedAt).getTime() - new Date(a.capturedAt).getTime() || String(b.id).localeCompare(String(a.id)));
1973
+ const currentAttempt = leaves[0] ?? null;
1974
+ const revisions = currentAttempt ? await (await WorkbookAssessmentRevisionCollection.create({ db })).list({ where: {
1975
+ tenantId: scope.tenantId,
1976
+ learnerId: scope.learnerId,
1977
+ attemptId: String(currentAttempt.id)
1978
+ } }) : [];
1979
+ revisions.sort((a, b) => new Date(b.recordedAt).getTime() - new Date(a.recordedAt).getTime() || String(b.id).localeCompare(String(a.id)));
1980
+ const head = revisions.find((revision) => revision.kind === "guardian") ?? revisions.find((revision) => revision.kind === "ai");
1981
+ const decisions = await db.tableExists("workbook_completion_decisions") ? await (await WorkbookCompletionDecisionCollection.create({ db })).list({ where: scope }) : [];
1982
+ const currentDecisions = decisions.filter((decision2) => decision2.attemptId === currentAttempt?.id);
1983
+ if (currentDecisions.length > 1) throw new Error("Workbook current completion decision is ambiguous");
1984
+ const decision = currentDecisions[0] ?? null;
1985
+ if (decision && decision.submissionId !== currentAttempt?.submissionId) throw new Error("Workbook completion submission mismatch");
1986
+ return {
1987
+ currentAttempt,
1988
+ feedbackHeadId: head ? String(head.id) : null,
1989
+ decision,
1990
+ decisions,
1991
+ completion: decision ? {
1992
+ status: "complete",
1993
+ completedAt: new Date(decision.recordedAt)
1994
+ } : {
1995
+ status: "doing",
1996
+ completedAt: null
1997
+ },
1998
+ attempts
1999
+ };
2000
+ }
2001
+ //#endregion
1824
2002
  //#region src/learner-service.ts
1825
2003
  var LearnerAuthorizationError = class extends Error {
1826
2004
  constructor() {
@@ -2019,7 +2197,10 @@ var LearnerService = class LearnerService {
2019
2197
  if (own && [
2020
2198
  "education.learner.plan",
2021
2199
  "education.learner.grade",
2022
- "education.learner.packet"
2200
+ "education.learner.packet",
2201
+ "education.learner.notes.read",
2202
+ "education.learner.notes.add",
2203
+ "education.learner.complete"
2023
2204
  ].includes(action)) throw new LearnerAuthorizationError();
2024
2205
  if (await this.authorize({
2025
2206
  ...request,
@@ -2255,15 +2436,25 @@ var LearnerService = class LearnerService {
2255
2436
  /** Compatibility progress never transports a workbook learner's feedback. */
2256
2437
  async projectProgress(request, row) {
2257
2438
  const view = progressView(row);
2258
- if ((await this.db.get("learners", {
2439
+ const activity = await this.findWorkbookActivity(request, {
2440
+ enrollmentId: row.enrollmentId,
2441
+ lessonId: row.lessonId
2442
+ });
2443
+ if (!activity) return view;
2444
+ const state = await readWorkbookCompletion(this.db, {
2445
+ tenantId: request.tenantId,
2446
+ learnerId: request.learnerId,
2447
+ activityId: String(activity.id)
2448
+ });
2449
+ const learner = await this.db.get("learners", {
2259
2450
  id: request.learnerId,
2260
2451
  tenant_id: request.tenantId
2261
- }))?.user_id !== request.actorUserId || !await this.findWorkbookActivity(request, { lessonId: row.lessonId })) return view;
2452
+ });
2262
2453
  return {
2263
2454
  ...view,
2264
- bestScore: null,
2265
- completedAt: null,
2266
- status: view.status === "complete" ? "submitted" : view.status
2455
+ status: state.completion.status === "complete" ? "complete" : ["complete", "skipped"].includes(view.status) ? "in_progress" : view.status,
2456
+ completedAt: state.completion.completedAt,
2457
+ ...learner?.user_id === request.actorUserId ? { bestScore: null } : {}
2267
2458
  };
2268
2459
  }
2269
2460
  async listProgress(request) {
@@ -25107,9 +25298,13 @@ var SubmissionService = class SubmissionService extends LearnerService {
25107
25298
  "application/pdf"
25108
25299
  ].includes(page.mimeType) || !Buffer.isBuffer(page.data) || !page.data.length || page.data.length > 25 * 1024 * 1024) throw new Error("Invalid capture page");
25109
25300
  }
25301
+ async lockProgressOwner(request) {
25302
+ if (await this.findWorkbookActivity(request, { enrollmentId: request.enrollmentId })) await this.db.query("UPDATE learners SET id = id WHERE id = ? AND tenant_id = ?", [request.learnerId, request.tenantId]);
25303
+ await this.lock("enrollments", request.enrollmentId, request.tenantId);
25304
+ }
25110
25305
  async progress(request, action) {
25111
25306
  const enrollment = await this.requireEnrollment(request, action);
25112
- await this.lock("enrollments", request.enrollmentId, request.tenantId);
25307
+ await this.lockProgressOwner(request);
25113
25308
  if (!(await this.catalog(request, enrollment.courseId)).sections.some((section) => section.lessons.some(({ lesson }) => lesson.id === request.lessonId))) throw new LearnerAuthorizationError();
25114
25309
  const collection = await LessonProgressCollection.create({ db: this.db });
25115
25310
  let progress = await collection.get({
@@ -25469,8 +25664,17 @@ var SubmissionService = class SubmissionService extends LearnerService {
25469
25664
  });
25470
25665
  row.status = "graded";
25471
25666
  await row.save();
25472
- progress.status = "complete";
25473
- progress.completedAt = /* @__PURE__ */ new Date();
25667
+ const workbookActivity = await this.findWorkbookActivity(request, {
25668
+ enrollmentId: progress.enrollmentId,
25669
+ lessonId: row.lessonId
25670
+ });
25671
+ const completion = workbookActivity ? await readWorkbookCompletion(this.db, {
25672
+ tenantId: request.tenantId,
25673
+ learnerId: request.learnerId,
25674
+ activityId: String(workbookActivity.id)
25675
+ }) : null;
25676
+ progress.status = completion ? completion.completion.status === "complete" ? "complete" : "in_progress" : "complete";
25677
+ progress.completedAt = completion ? completion.completion.completedAt : /* @__PURE__ */ new Date();
25474
25678
  progress.bestScore = score;
25475
25679
  await progress.save();
25476
25680
  return this.view(row, request.actorUserId);
@@ -25478,7 +25682,7 @@ var SubmissionService = class SubmissionService extends LearnerService {
25478
25682
  async reviewSubmission(request) {
25479
25683
  return this.mutate(async (service) => {
25480
25684
  await service.requireEnrollment(request, "education.learner.grade");
25481
- await service.lock("enrollments", request.enrollmentId, request.tenantId);
25685
+ await service.lockProgressOwner(request);
25482
25686
  const { row, progress } = await service.requireSubmission(request, "education.learner.grade");
25483
25687
  if (row.kind !== "completed_work") throw new Error("Blank workbook references cannot be graded");
25484
25688
  if ((await (await SubmissionCollection.create({ db: service.db })).list({ where: {
@@ -26018,6 +26222,17 @@ function revisionView(row) {
26018
26222
  assessment: JSON.parse(row.assessmentJson)
26019
26223
  };
26020
26224
  }
26225
+ function completionDecisionView(row) {
26226
+ return {
26227
+ id: String(row.id),
26228
+ activityId: row.activityId,
26229
+ attemptId: row.attemptId,
26230
+ submissionId: row.submissionId,
26231
+ feedbackHeadId: row.feedbackHeadId,
26232
+ actorUserId: row.actorUserId,
26233
+ completedAt: new Date(row.recordedAt)
26234
+ };
26235
+ }
26021
26236
  var WorkbookService = class WorkbookService extends SubmissionService {
26022
26237
  constructor(db, authorize, authorizeCatalog, workbookOptions) {
26023
26238
  super(db, authorize, authorizeCatalog, workbookOptions);
@@ -26086,7 +26301,15 @@ var WorkbookService = class WorkbookService extends SubmissionService {
26086
26301
  workbookId: head.workbookId
26087
26302
  }, { cache: false }) : null;
26088
26303
  if (head && (!projectedBook || head.canonicalActivityId && !target)) throw new LearnerAuthorizationError();
26304
+ const completion = await readWorkbookCompletion(this.db, {
26305
+ tenantId: row.tenantId,
26306
+ learnerId: row.learnerId,
26307
+ activityId: String(row.id)
26308
+ });
26089
26309
  return {
26310
+ currentAttemptId: completion.currentAttempt ? String(completion.currentAttempt.id) : null,
26311
+ latestSubmissionId: completion.currentAttempt?.submissionId ?? null,
26312
+ completion: completion.completion,
26090
26313
  id: String(row.id),
26091
26314
  learnerId: row.learnerId,
26092
26315
  workbookKey: projectedBook?.workbookKey ?? "",
@@ -26521,6 +26744,21 @@ var WorkbookService = class WorkbookService extends SubmissionService {
26521
26744
  previous = predecessor.attempt;
26522
26745
  if (predecessor.learner.userId === request.actorUserId && !await service.questionIdentityVisible(request, previous, await service.identityRevision(request, previous))) throw new LearnerAuthorizationError();
26523
26746
  }
26747
+ if (request.previousSubmissionId) {
26748
+ const current = await readWorkbookCompletion(service.db, {
26749
+ tenantId: request.tenantId,
26750
+ learnerId: request.learnerId,
26751
+ activityId: request.activityId
26752
+ });
26753
+ if (current.currentAttempt?.submissionId !== request.previousSubmissionId) {
26754
+ if (!(await (await SubmissionCollection.create({ db: service.db })).list({ where: {
26755
+ tenantId: request.tenantId,
26756
+ learnerId: request.learnerId,
26757
+ lessonId: row.lessonId,
26758
+ captureKey: request.requestKey
26759
+ } })).some((submission2) => current.attempts.some((attempt2) => attempt2.submissionId === submission2.id))) throw new WorkbookCompletionConflictError("stale_attempt");
26760
+ }
26761
+ }
26524
26762
  const capture = {
26525
26763
  ...request,
26526
26764
  enrollmentId: row.enrollmentId,
@@ -26563,7 +26801,11 @@ var WorkbookService = class WorkbookService extends SubmissionService {
26563
26801
  policyVersion: workbook?.policyVersion ?? 1,
26564
26802
  assistance,
26565
26803
  actorUserId: request.actorUserId,
26566
- capturedAt: submission.submittedAt,
26804
+ capturedAt: new Date(Math.max(new Date(submission.submittedAt).getTime(), ...(await attempts.list({ where: {
26805
+ tenantId: request.tenantId,
26806
+ learnerId: request.learnerId,
26807
+ activityId: request.activityId
26808
+ } })).map((prior2) => new Date(prior2.capturedAt).getTime() + 1))),
26567
26809
  sourceHashes: JSON.stringify(sourceHashes)
26568
26810
  });
26569
26811
  return service.attemptView(request, row, attempt);
@@ -26875,6 +27117,57 @@ var WorkbookService = class WorkbookService extends SubmissionService {
26875
27117
  return revisionView(result.row);
26876
27118
  });
26877
27119
  }
27120
+ async completeWorkbookActivity(request) {
27121
+ return this.composeMutation(async (service) => {
27122
+ await service.requireActor(request, "education.learner.complete");
27123
+ await service.serialize(request);
27124
+ const { row } = await service.activity(request, "education.learner.complete");
27125
+ nonempty(request.requestKey, "completion request key");
27126
+ nonempty(request.expectedAttemptId, "completion attempt");
27127
+ nonempty(request.submissionId, "completion submission");
27128
+ if (request.expectedHeadId !== null) nonempty(request.expectedHeadId, "completion feedback head");
27129
+ const decisions = await WorkbookCompletionDecisionCollection.create({ db: service.db });
27130
+ const prior = await decisions.get({
27131
+ tenantId: request.tenantId,
27132
+ activityId: request.activityId,
27133
+ requestKey: request.requestKey
27134
+ }, { cache: false });
27135
+ if (prior) {
27136
+ if (prior.learnerId !== request.learnerId || prior.actorUserId !== request.actorUserId || prior.attemptId !== request.expectedAttemptId || prior.submissionId !== request.submissionId || prior.feedbackHeadId !== request.expectedHeadId) throw new WorkbookCompletionConflictError("changed_retry");
27137
+ return completionDecisionView(prior);
27138
+ }
27139
+ const current = await readWorkbookCompletion(service.db, {
27140
+ tenantId: request.tenantId,
27141
+ learnerId: request.learnerId,
27142
+ activityId: request.activityId
27143
+ });
27144
+ if (!current.currentAttempt || current.currentAttempt.id !== request.expectedAttemptId || current.currentAttempt.submissionId !== request.submissionId) throw new WorkbookCompletionConflictError("stale_attempt");
27145
+ if (current.feedbackHeadId !== request.expectedHeadId) throw new WorkbookCompletionConflictError("stale_head");
27146
+ if (current.decision) throw new WorkbookCompletionConflictError("already_complete");
27147
+ const decision = await decisions.create({
27148
+ tenantId: request.tenantId,
27149
+ learnerId: request.learnerId,
27150
+ activityId: request.activityId,
27151
+ attemptId: request.expectedAttemptId,
27152
+ submissionId: request.submissionId,
27153
+ feedbackHeadId: request.expectedHeadId,
27154
+ actorUserId: request.actorUserId,
27155
+ requestKey: request.requestKey,
27156
+ _insertOnly: true
27157
+ });
27158
+ const progress = await (await LessonProgressCollection.create({ db: service.db })).get({
27159
+ tenantId: request.tenantId,
27160
+ learnerId: request.learnerId,
27161
+ enrollmentId: row.enrollmentId,
27162
+ lessonId: row.lessonId
27163
+ }, { cache: false });
27164
+ if (!progress) throw new LearnerAuthorizationError();
27165
+ progress.status = "complete";
27166
+ progress.completedAt = new Date(decision.recordedAt);
27167
+ await progress.save();
27168
+ return completionDecisionView(decision);
27169
+ });
27170
+ }
26878
27171
  async releaseWorkbookFeedback(request) {
26879
27172
  return this.composeMutation(async (service) => {
26880
27173
  await service.requireActor(request, "education.learner.grade");
@@ -26958,6 +27251,11 @@ var WorkbookService = class WorkbookService extends SubmissionService {
26958
27251
  async getWorkbookTimeline(request) {
26959
27252
  const { row, workbook, learner } = await this.activity(request);
26960
27253
  const own = learner.userId === request.actorUserId;
27254
+ const completion = await readWorkbookCompletion(this.db, {
27255
+ tenantId: request.tenantId,
27256
+ learnerId: request.learnerId,
27257
+ activityId: request.activityId
27258
+ });
26961
27259
  const limit = request.limit ?? 25;
26962
27260
  if (!Number.isSafeInteger(limit) || limit < 1 || limit > 100) throw new Error("Invalid timeline limit");
26963
27261
  const all = await (await WorkbookAttemptCollection.create({ db: this.db })).list({
@@ -27014,10 +27312,22 @@ var WorkbookService = class WorkbookService extends SubmissionService {
27014
27312
  actorUserId: d.actorUserId,
27015
27313
  createdAt: d.recordedAt
27016
27314
  })),
27017
- headId: own ? null : headId ? String(headId) : null
27315
+ headId: own ? null : headId ? String(headId) : null,
27316
+ completionDecision: own ? null : (() => {
27317
+ const decision = completion.decisions.find((value) => value.attemptId === attempt.id);
27318
+ return decision ? completionDecisionView(decision) : null;
27319
+ })()
27018
27320
  });
27019
27321
  }
27020
27322
  return {
27323
+ currentAttemptId: completion.currentAttempt ? String(completion.currentAttempt.id) : null,
27324
+ latestSubmissionId: completion.currentAttempt?.submissionId ?? null,
27325
+ completion: completion.completion,
27326
+ completionContext: own || !completion.currentAttempt ? null : {
27327
+ attemptId: String(completion.currentAttempt.id),
27328
+ submissionId: completion.currentAttempt.submissionId,
27329
+ expectedHeadId: completion.feedbackHeadId
27330
+ },
27021
27331
  activity: await this.activityView(row, workbook),
27022
27332
  attempts,
27023
27333
  nextCursor: start + limit < all.length ? String(all[start + limit - 1].id) : null
@@ -27600,6 +27910,6 @@ var WorkbookPhotoService = class WorkbookPhotoService extends WorkbookService {
27600
27910
  }
27601
27911
  };
27602
27912
  //#endregion
27603
- export { EnrollmentCollection as $, WorkbookFeedbackRelease as A, Exercise as At, FamilyIntakeAsset as B, WorkbookAssessmentRevision as C, Curriculum as Ct, WorkbookCollection as D, AuthoredCourse as Dt, WorkbookAttemptCollection as E, LessonProgress as Et, WorkbookAssessmentValidationError as F, Worksheet as Ft, familyIntakeScopeId as G, FamilyIntakeCollection as H, aggregateWorkbookQuestions as I, AttestationCollection as J, CatalogAuthorizationError as K, validateWorkbookAssessment as L, WorkbookWorkFiling as M, Lesson as Mt, WorkbookWorkFilingCollection as N, Reading as Nt, WorkbookFeedbackDelivery as O, Course as Ot, WORKBOOK_MATH_VOCABULARY as P, Video as Pt, CurriculumCollection as Q, workbookAggregateFeedback as R, WorkbookActivityCollection as S, LessonAsset as St, WorkbookAttempt as T, Learner as Tt, FamilyIntakeDecision as U, FamilyIntakeAssetCollection as V, FamilyIntakeDecisionCollection as W, CourseCollection as X, AuthoredCourseCollection as Y, CourseSectionCollection as Z, WorkbookWorkflowRequiredError as _, Grade as _t, WorkbookContextRevisionCollection as a, LessonAssetCollection as at, Workbook as b, SubmissionAsset as bt, WorkbookPhotoDecision as c, ReadingCollection as ct, WorkbookPhotoIntakeCollection as d, SubmissionCollection as dt, ExerciseCollection as et, validateWorkbookPhotoIdentification as f, SubmissionIntakeBindingCollection as ft, SubmissionStorageCleanupError as g, ExternalCompletion as gt, SubmissionService as h, Attestation as ht, WorkbookContextRevision as i, LearnerCollection as it, WorkbookFeedbackReleaseCollection as j, ExternalCourse as jt, WorkbookFeedbackDeliveryCollection as k, CourseSection as kt, WorkbookPhotoDecisionCollection as l, ScannedSubmissionCollection as lt, normalizeWorkbookAnswerRegions as m, WorksheetCollection as mt, preservePhotoProposal as n, ExternalCourseCollection as nt, WorkbookPhotoAsset as o, LessonCollection as ot, normalizeWorkbookObservedLayout as p, VideoCollection as pt, CatalogService as q, WorkbookService as r, GradeCollection as rt, WorkbookPhotoAssetCollection as s, LessonProgressCollection as st, WorkbookPhotoService as t, ExternalCompletionCollection as tt, WorkbookPhotoIntake as u, SubmissionAssetCollection as ut, LearnerAuthorizationError as v, ScannedSubmission as vt, WorkbookAssessmentRevisionCollection as w, Enrollment as wt, WorkbookActivity as x, SubmissionIntakeBinding as xt, LearnerService as y, Submission as yt, FamilyIntake as z };
27913
+ export { CourseCollection as $, WorkbookFeedbackDelivery as A, AuthoredCourse as At, validateWorkbookAssessment as B, WorkbookActivity as C, SubmissionAsset as Ct, WorkbookAttempt as D, Enrollment as Dt, WorkbookAssessmentRevisionCollection as E, Curriculum as Et, WorkbookWorkFilingCollection as F, Lesson as Ft, FamilyIntakeCollection as G, FamilyIntake as H, WORKBOOK_MATH_VOCABULARY as I, Reading as It, familyIntakeScopeId as J, FamilyIntakeDecision as K, WorkbookAssessmentValidationError as L, Video as Lt, WorkbookFeedbackRelease as M, CourseSection as Mt, WorkbookFeedbackReleaseCollection as N, Exercise as Nt, WorkbookAttemptCollection as O, Learner as Ot, WorkbookWorkFiling as P, ExternalCourse as Pt, AuthoredCourseCollection as Q, WorkbookCompletionConflictError as R, Worksheet as Rt, Workbook as S, Submission as St, WorkbookAssessmentRevision as T, LessonAsset as Tt, FamilyIntakeAsset as U, workbookAggregateFeedback as V, FamilyIntakeAssetCollection as W, CatalogService as X, CatalogAuthorizationError as Y, AttestationCollection as Z, WorkbookWorkflowRequiredError as _, WorksheetCollection as _t, WorkbookContextRevisionCollection as a, ExternalCourseCollection as at, WorkbookCompletionDecision as b, Grade as bt, WorkbookPhotoDecision as c, LessonAssetCollection as ct, WorkbookPhotoIntakeCollection as d, ReadingCollection as dt, CourseSectionCollection as et, validateWorkbookPhotoIdentification as f, ScannedSubmissionCollection as ft, SubmissionStorageCleanupError as g, VideoCollection as gt, SubmissionService as h, SubmissionIntakeBindingCollection as ht, WorkbookContextRevision as i, ExternalCompletionCollection as it, WorkbookFeedbackDeliveryCollection as j, Course as jt, WorkbookCollection as k, LessonProgress as kt, WorkbookPhotoDecisionCollection as l, LessonCollection as lt, normalizeWorkbookAnswerRegions as m, SubmissionCollection as mt, preservePhotoProposal as n, EnrollmentCollection as nt, WorkbookPhotoAsset as o, GradeCollection as ot, normalizeWorkbookObservedLayout as p, SubmissionAssetCollection as pt, FamilyIntakeDecisionCollection as q, WorkbookService as r, ExerciseCollection as rt, WorkbookPhotoAssetCollection as s, LearnerCollection as st, WorkbookPhotoService as t, CurriculumCollection as tt, WorkbookPhotoIntake as u, LessonProgressCollection as ut, LearnerAuthorizationError as v, Attestation as vt, WorkbookActivityCollection as w, SubmissionIntakeBinding as wt, WorkbookCompletionDecisionCollection as x, ScannedSubmission as xt, LearnerService as y, ExternalCompletion as yt, aggregateWorkbookQuestions as z };
27604
27914
 
27605
- //# sourceMappingURL=workbook-photo-service-DCmqeWLd.js.map
27915
+ //# sourceMappingURL=workbook-photo-service-D5DUgh-C.js.map