@driveup/schema 0.2.6 → 0.2.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (220) hide show
  1. package/lib/catalog/addon/addon.entity.d.ts +3 -3
  2. package/lib/catalog/addon/addon.entity.js +7 -7
  3. package/lib/catalog/addon/addon.entity.js.map +1 -1
  4. package/lib/catalog/addon/country.entity.d.ts +4 -4
  5. package/lib/catalog/addon/country.entity.js +5 -6
  6. package/lib/catalog/addon/country.entity.js.map +1 -1
  7. package/lib/catalog/priceplan/priceplan.entity.d.ts +8 -3
  8. package/lib/catalog/priceplan/priceplan.entity.js +14 -7
  9. package/lib/catalog/priceplan/priceplan.entity.js.map +1 -1
  10. package/lib/catalog/product/country.entity.d.ts +6 -6
  11. package/lib/catalog/product/country.entity.js +9 -10
  12. package/lib/catalog/product/country.entity.js.map +1 -1
  13. package/lib/catalog/product/priceplan.entity.d.ts +9 -4
  14. package/lib/catalog/product/priceplan.entity.js +19 -9
  15. package/lib/catalog/product/priceplan.entity.js.map +1 -1
  16. package/lib/catalog/product/product.entity.d.ts +3 -3
  17. package/lib/catalog/product/product.entity.js +8 -8
  18. package/lib/catalog/product/product.entity.js.map +1 -1
  19. package/lib/catalog/program/program.entity.d.ts +2 -2
  20. package/lib/catalog/program/program.entity.js +7 -7
  21. package/lib/catalog/program/program.entity.js.map +1 -1
  22. package/lib/catalog/seed/assets/asset.entity.d.ts +2 -2
  23. package/lib/catalog/seed/assets/asset.entity.js +6 -6
  24. package/lib/catalog/seed/assets/asset.entity.js.map +1 -1
  25. package/lib/catalog/seed/courses/course.entity.d.ts +4 -4
  26. package/lib/catalog/seed/courses/course.entity.js +9 -9
  27. package/lib/catalog/seed/courses/course.entity.js.map +1 -1
  28. package/lib/catalog/seed/courses/lesson.entity.d.ts +3 -3
  29. package/lib/catalog/seed/courses/lesson.entity.js +7 -7
  30. package/lib/catalog/seed/courses/lesson.entity.js.map +1 -1
  31. package/lib/catalog/seed/courses/topic.entity.d.ts +3 -3
  32. package/lib/catalog/seed/courses/topic.entity.js +8 -8
  33. package/lib/catalog/seed/courses/topic.entity.js.map +1 -1
  34. package/lib/catalog/seed/expense/category.entity.d.ts +2 -2
  35. package/lib/catalog/seed/expense/category.entity.js +6 -6
  36. package/lib/catalog/seed/expense/category.entity.js.map +1 -1
  37. package/lib/index.d.ts +2 -2
  38. package/lib/index.js +2 -2
  39. package/lib/index.js.map +1 -1
  40. package/lib/profile/agent/agent.entity.d.ts +13 -4
  41. package/lib/profile/agent/agent.entity.js +46 -20
  42. package/lib/profile/agent/agent.entity.js.map +1 -1
  43. package/lib/profile/agent/asset.entity.d.ts +1 -1
  44. package/lib/profile/agent/asset.entity.js +2 -2
  45. package/lib/profile/agent/asset.entity.js.map +1 -1
  46. package/lib/profile/agent/payout.entity.d.ts +3 -3
  47. package/lib/profile/agent/payout.entity.js +6 -6
  48. package/lib/profile/agent/payout.entity.js.map +1 -1
  49. package/lib/profile/agent/promotion.entity.d.ts +3 -3
  50. package/lib/profile/agent/promotion.entity.js +6 -6
  51. package/lib/profile/agent/promotion.entity.js.map +1 -1
  52. package/lib/profile/company/company.entity.d.ts +80 -9
  53. package/lib/profile/company/company.entity.js +246 -36
  54. package/lib/profile/company/company.entity.js.map +1 -1
  55. package/lib/profile/company/course/appointment.entity.d.ts +73 -4
  56. package/lib/profile/company/course/appointment.entity.js +247 -0
  57. package/lib/profile/company/course/appointment.entity.js.map +1 -1
  58. package/lib/profile/company/course/course.entity.d.ts +41 -8
  59. package/lib/profile/company/course/course.entity.js +58 -12
  60. package/lib/profile/company/course/course.entity.js.map +1 -1
  61. package/lib/profile/company/course/lesson.entity.d.ts +30 -7
  62. package/lib/profile/company/course/lesson.entity.js +93 -12
  63. package/lib/profile/company/course/lesson.entity.js.map +1 -1
  64. package/lib/profile/company/course/schedule.entity.d.ts +276 -0
  65. package/lib/profile/company/course/schedule.entity.js +744 -0
  66. package/lib/profile/company/course/schedule.entity.js.map +1 -0
  67. package/lib/profile/company/course/topic.entity.d.ts +9 -4
  68. package/lib/profile/company/course/topic.entity.js +14 -7
  69. package/lib/profile/company/course/topic.entity.js.map +1 -1
  70. package/lib/profile/company/finances/billing/bill.entity.d.ts +9 -2
  71. package/lib/profile/company/finances/billing/bill.entity.js +38 -4
  72. package/lib/profile/company/finances/billing/bill.entity.js.map +1 -1
  73. package/lib/profile/company/finances/billing/item.entity.d.ts +8 -3
  74. package/lib/profile/company/finances/billing/item.entity.js +10 -6
  75. package/lib/profile/company/finances/billing/item.entity.js.map +1 -1
  76. package/lib/profile/company/finances/billing/transaction.entity.d.ts +7 -5
  77. package/lib/profile/company/finances/billing/transaction.entity.js +6 -6
  78. package/lib/profile/company/finances/billing/transaction.entity.js.map +1 -1
  79. package/lib/profile/company/finances/expense/category.entity.d.ts +1 -1
  80. package/lib/profile/company/finances/expense/category.entity.js +4 -4
  81. package/lib/profile/company/finances/expense/category.entity.js.map +1 -1
  82. package/lib/profile/company/finances/expense/expense.entity.d.ts +6 -2
  83. package/lib/profile/company/finances/expense/expense.entity.js +32 -4
  84. package/lib/profile/company/finances/expense/expense.entity.js.map +1 -1
  85. package/lib/profile/company/finances/handover/handover.entity.d.ts +3 -3
  86. package/lib/profile/company/finances/handover/handover.entity.js +6 -6
  87. package/lib/profile/company/finances/handover/handover.entity.js.map +1 -1
  88. package/lib/profile/company/finances/invoice/invoice.entity.d.ts +8 -7
  89. package/lib/profile/company/finances/invoice/invoice.entity.js +15 -14
  90. package/lib/profile/company/finances/invoice/invoice.entity.js.map +1 -1
  91. package/lib/profile/company/finances/invoice/item.entity.d.ts +2 -2
  92. package/lib/profile/company/finances/invoice/item.entity.js +4 -4
  93. package/lib/profile/company/finances/invoice/item.entity.js.map +1 -1
  94. package/lib/profile/company/finances/payment/method.entity.d.ts +24 -4
  95. package/lib/profile/company/finances/payment/method.entity.js +40 -5
  96. package/lib/profile/company/finances/payment/method.entity.js.map +1 -1
  97. package/lib/profile/company/instructor/activity.entity.js.map +1 -1
  98. package/lib/profile/company/instructor/calendar-state.entity.js.map +1 -1
  99. package/lib/profile/company/instructor/instructor.entity.d.ts +34 -17
  100. package/lib/profile/company/instructor/instructor.entity.js +143 -25
  101. package/lib/profile/company/instructor/instructor.entity.js.map +1 -1
  102. package/lib/profile/company/instructor/task.entity.d.ts +2 -1
  103. package/lib/profile/company/instructor/task.entity.js +9 -4
  104. package/lib/profile/company/instructor/task.entity.js.map +1 -1
  105. package/lib/profile/company/medical/examination.entity.d.ts +4 -4
  106. package/lib/profile/company/medical/examination.entity.js +6 -6
  107. package/lib/profile/company/medical/examination.entity.js.map +1 -1
  108. package/lib/profile/company/medical/product.entity.d.ts +4 -5
  109. package/lib/profile/company/medical/product.entity.js +13 -14
  110. package/lib/profile/company/medical/product.entity.js.map +1 -1
  111. package/lib/profile/company/product/addon.entity.d.ts +3 -3
  112. package/lib/profile/company/product/addon.entity.js +6 -7
  113. package/lib/profile/company/product/addon.entity.js.map +1 -1
  114. package/lib/profile/company/product/priceplan.entity.d.ts +15 -13
  115. package/lib/profile/company/product/priceplan.entity.js +20 -16
  116. package/lib/profile/company/product/priceplan.entity.js.map +1 -1
  117. package/lib/profile/company/product/product.entity.d.ts +34 -8
  118. package/lib/profile/company/product/product.entity.js +70 -12
  119. package/lib/profile/company/product/product.entity.js.map +1 -1
  120. package/lib/profile/company/product/vehicle.entity.d.ts +2 -2
  121. package/lib/profile/company/product/vehicle.entity.js +4 -4
  122. package/lib/profile/company/product/vehicle.entity.js.map +1 -1
  123. package/lib/profile/instructor/instructor.entity.d.ts +6 -3
  124. package/lib/profile/instructor/instructor.entity.js +31 -9
  125. package/lib/profile/instructor/instructor.entity.js.map +1 -1
  126. package/lib/profile/student/program/licence/licence.entity.d.ts +13 -5
  127. package/lib/profile/student/program/licence/licence.entity.js +19 -8
  128. package/lib/profile/student/program/licence/licence.entity.js.map +1 -1
  129. package/lib/profile/student/program/medical/certificate.entity.d.ts +3 -3
  130. package/lib/profile/student/program/medical/certificate.entity.js +6 -6
  131. package/lib/profile/student/program/medical/certificate.entity.js.map +1 -1
  132. package/lib/profile/student/program/medical/examination.entity.d.ts +4 -4
  133. package/lib/profile/student/program/medical/examination.entity.js +14 -14
  134. package/lib/profile/student/program/medical/examination.entity.js.map +1 -1
  135. package/lib/profile/student/program/program.entity.d.ts +4 -4
  136. package/lib/profile/student/program/program.entity.js +8 -13
  137. package/lib/profile/student/program/program.entity.js.map +1 -1
  138. package/lib/profile/student/program/training/appointment.entity.d.ts +32 -9
  139. package/lib/profile/student/program/training/appointment.entity.js +144 -21
  140. package/lib/profile/student/program/training/appointment.entity.js.map +1 -1
  141. package/lib/profile/student/program/training/exam.entity.d.ts +9 -2
  142. package/lib/profile/student/program/training/exam.entity.js +28 -12
  143. package/lib/profile/student/program/training/exam.entity.js.map +1 -1
  144. package/lib/profile/student/program/training/lesson.entity.d.ts +8 -3
  145. package/lib/profile/student/program/training/lesson.entity.js +28 -6
  146. package/lib/profile/student/program/training/lesson.entity.js.map +1 -1
  147. package/lib/profile/student/program/training/request.entity.d.ts +6 -3
  148. package/lib/profile/student/program/training/request.entity.js +26 -5
  149. package/lib/profile/student/program/training/request.entity.js.map +1 -1
  150. package/lib/profile/student/program/training/topic.entity.d.ts +16 -4
  151. package/lib/profile/student/program/training/topic.entity.js +36 -9
  152. package/lib/profile/student/program/training/topic.entity.js.map +1 -1
  153. package/lib/profile/student/program/training/training.entity.d.ts +50 -6
  154. package/lib/profile/student/program/training/training.entity.js +217 -33
  155. package/lib/profile/student/program/training/training.entity.js.map +1 -1
  156. package/lib/profile/student/program/training/transaction.entity.d.ts +8 -3
  157. package/lib/profile/student/program/training/transaction.entity.js +43 -6
  158. package/lib/profile/student/program/training/transaction.entity.js.map +1 -1
  159. package/lib/profile/student/student.entity.d.ts +11 -6
  160. package/lib/profile/student/student.entity.js +59 -11
  161. package/lib/profile/student/student.entity.js.map +1 -1
  162. package/lib/system/campaign/campaign.entity.d.ts +4 -4
  163. package/lib/system/campaign/campaign.entity.js +10 -10
  164. package/lib/system/campaign/campaign.entity.js.map +1 -1
  165. package/lib/system/campaign/gifcode.entity.d.ts +4 -4
  166. package/lib/system/campaign/gifcode.entity.js +8 -8
  167. package/lib/system/campaign/gifcode.entity.js.map +1 -1
  168. package/lib/system/country/country.entity.d.ts +8 -6
  169. package/lib/system/country/country.entity.js +15 -9
  170. package/lib/system/country/country.entity.js.map +1 -1
  171. package/lib/system/currency/currency.entity.d.ts +1 -1
  172. package/lib/system/currency/currency.entity.js +4 -4
  173. package/lib/system/currency/currency.entity.js.map +1 -1
  174. package/lib/system/driving/category.entity.d.ts +7 -7
  175. package/lib/system/driving/category.entity.js +14 -14
  176. package/lib/system/driving/category.entity.js.map +1 -1
  177. package/lib/system/driving/vehicle.entity.d.ts +2 -2
  178. package/lib/system/driving/vehicle.entity.js +4 -4
  179. package/lib/system/driving/vehicle.entity.js.map +1 -1
  180. package/lib/system/event/event.entity.d.ts +2 -2
  181. package/lib/system/event/event.entity.js +4 -4
  182. package/lib/system/event/event.entity.js.map +1 -1
  183. package/lib/system/event/log.entity.d.ts +2 -2
  184. package/lib/system/event/log.entity.js +3 -3
  185. package/lib/system/event/log.entity.js.map +1 -1
  186. package/lib/system/ical/ical.entity.d.ts +63 -0
  187. package/lib/system/ical/ical.entity.js +70 -0
  188. package/lib/system/ical/ical.entity.js.map +1 -0
  189. package/lib/system/policy/policy.entity.d.ts +2 -2
  190. package/lib/system/policy/policy.entity.js +8 -8
  191. package/lib/system/policy/policy.entity.js.map +1 -1
  192. package/lib/system/staff/staff.entity.d.ts +1 -1
  193. package/lib/system/staff/staff.entity.js +5 -4
  194. package/lib/system/staff/staff.entity.js.map +1 -1
  195. package/lib/tsconfig.tsbuildinfo +1 -1
  196. package/lib/user/alert.entity.d.ts +4 -3
  197. package/lib/user/alert.entity.js +11 -4
  198. package/lib/user/alert.entity.js.map +1 -1
  199. package/lib/user/blocked.entity.js +2 -2
  200. package/lib/user/blocked.entity.js.map +1 -1
  201. package/lib/user/device.entity.d.ts +17 -2
  202. package/lib/user/device.entity.js +29 -3
  203. package/lib/user/device.entity.js.map +1 -1
  204. package/lib/user/notification.entity.d.ts +3 -3
  205. package/lib/user/notification.entity.js +8 -8
  206. package/lib/user/notification.entity.js.map +1 -1
  207. package/lib/user/ticket.entity.d.ts +8 -3
  208. package/lib/user/ticket.entity.js +16 -7
  209. package/lib/user/ticket.entity.js.map +1 -1
  210. package/lib/user/user.entity.d.ts +101 -89
  211. package/lib/user/user.entity.js +272 -270
  212. package/lib/user/user.entity.js.map +1 -1
  213. package/lib/user/verification.entity.js +2 -2
  214. package/lib/user/verification.entity.js.map +1 -1
  215. package/lib/utils/activity.helper.d.ts +2 -2
  216. package/lib/utils/activity.helper.js.map +1 -1
  217. package/lib/utils/trackable.d.ts +13 -2
  218. package/lib/utils/trackable.js +55 -0
  219. package/lib/utils/trackable.js.map +1 -1
  220. package/package.json +3 -3
@@ -11,24 +11,25 @@ var __metadata = (this && this.__metadata) || function (k, v) {
11
11
  var UserEntity_1;
12
12
  Object.defineProperty(exports, "__esModule", { value: true });
13
13
  exports.UserEntity = void 0;
14
- const typeorm_1 = require("typeorm");
15
- const nestjs_i18n_1 = require("nestjs-i18n");
16
- const shared_1 = require("@driveup/shared");
17
14
  const common_1 = require("@driveup/common");
18
- const log_entity_1 = require("../system/event/log.entity");
19
- const country_entity_1 = require("../system/country/country.entity");
20
- const company_entity_1 = require("../profile/company/company.entity");
21
- const instructor_entity_1 = require("../profile/instructor/instructor.entity");
22
- const instructor_entity_2 = require("../profile/company/instructor/instructor.entity");
15
+ const shared_1 = require("@driveup/shared");
16
+ const shared_2 = require("@driveup/shared");
17
+ const luxon_1 = require("luxon");
18
+ const typeorm_1 = require("typeorm");
23
19
  const agent_entity_1 = require("../profile/agent/agent.entity");
20
+ const company_entity_1 = require("../profile/company/company.entity");
21
+ const instructor_entity_1 = require("../profile/company/instructor/instructor.entity");
22
+ const instructor_entity_2 = require("../profile/instructor/instructor.entity");
23
+ const program_entity_1 = require("../profile/student/program/program.entity");
24
24
  const student_entity_1 = require("../profile/student/student.entity");
25
- const notification_entity_1 = require("./notification.entity");
25
+ const country_entity_1 = require("../system/country/country.entity");
26
+ const log_entity_1 = require("../system/event/log.entity");
27
+ const activity_helper_1 = require("../utils/activity.helper");
28
+ const trackable_1 = require("../utils/trackable");
29
+ const alert_entity_1 = require("./alert.entity");
26
30
  const device_entity_1 = require("./device.entity");
31
+ const notification_entity_1 = require("./notification.entity");
27
32
  const ticket_entity_1 = require("./ticket.entity");
28
- const alert_entity_1 = require("./alert.entity");
29
- const trackable_1 = require("../utils/trackable");
30
- const activity_helper_1 = require("../utils/activity.helper");
31
- const program_entity_1 = require("../profile/student/program/program.entity");
32
33
  /**
33
34
  * User entity representing a user in the system.
34
35
  * Extends TrackableEntity to track creation and update information.
@@ -68,307 +69,317 @@ let UserEntity = UserEntity_1 = class UserEntity extends trackable_1.TrackableEn
68
69
  * @returns Person model with basic contact information
69
70
  */
70
71
  toPerson() {
71
- return new common_1.Person({
72
+ return new shared_1.Person({
72
73
  id: this.id,
73
74
  name: this.name,
74
75
  phone: this.phone,
75
76
  email: this.email,
76
- imageUrl: this.imageUrl
77
+ imageUrl: this.imageUrl,
78
+ image: this.imageUrl // mvp only
77
79
  });
78
80
  }
79
81
  /**
80
- * Updates the last activity timestamp of the user to the current date and saves it.
81
- * Used to track when the user was last active in the system.
82
- * @returns The updated user entity
82
+ * Remove suffix from phone number if the account is closed
83
+ * @returns phone number that should be returned to ui
83
84
  */
84
- async updateActivity() {
85
- this.lastActivity = new Date();
86
- return await UserEntity_1.save(this);
85
+ getPhone() {
86
+ return this.status === shared_1.AccountStatus.Closed
87
+ ? this.phone.includes('-')
88
+ ? this.phone.split('-')[0]
89
+ : this.phone
90
+ : this.phone;
87
91
  }
88
- /**
89
- * Check if user last activity is overdated
90
- * @returns
91
- */
92
- isActivityOverdated(now) {
93
- if (!this.lastActivity) {
94
- return;
95
- }
96
- // the beginning of the time, before which the activity is considered overdated
97
- const startDate = now;
98
- // go back 180 days from now
99
- startDate.setDate(startDate.getDate() - 180);
100
- return this.lastActivity < startDate;
92
+ async hasPushNotificationsEnabled() {
93
+ const devices = await this.devices;
94
+ return devices?.filter(i => i.token).length > 0;
101
95
  }
96
+ /**************************** profiles ****************************/
102
97
  /**
103
- * Retrieves the user's student profile if it exists, excluding closed profiles
104
- * @returns The student profile or null if not found
98
+ * Retrieves the user's student profile if it exists
99
+ * User can have only one student profile which can be active or pending
100
+ * @returns The student profile
105
101
  */
106
- async getStudentProfile() {
107
- const students = await this.studentProfiles;
108
- return students?.length ? students.filter(i => i.status !== shared_1.AccountStatus.Closed)[0] : null;
102
+ async getStudent(manager) {
103
+ manager = manager ?? student_entity_1.StudentEntity.getRepository().manager;
104
+ const students = await manager.findBy(student_entity_1.StudentEntity, { userId: this.id });
105
+ return students?.find(i => i.status === shared_1.AccountStatus.Active)
106
+ || students?.find(i => i.status === shared_1.AccountStatus.Pending);
109
107
  }
110
108
  /**
111
- * Retrieves the user's active student profile
112
- * @returns The active student profile or null if not found
109
+ * Retrieves the user's agent profile if it exists
110
+ * User can have only one agent profile which can be active or pending
111
+ * @returns The agent profile
113
112
  */
114
- async getActiveStudentProfile() {
115
- let students = await this.studentProfiles;
116
- students = students?.filter(i => i.status === shared_1.AccountStatus.Active);
117
- return students?.length ? students[0] : null;
113
+ async getAgent(manager) {
114
+ manager = manager ?? agent_entity_1.AgentEntity.getRepository().manager;
115
+ const agents = await manager.findBy(agent_entity_1.AgentEntity, { userId: this.id });
116
+ return agents?.find(i => i.status === shared_1.AccountStatus.Active)
117
+ || agents?.find(i => i.status === shared_1.AccountStatus.Pending);
118
118
  }
119
119
  /**
120
- * Retrieves the user's agent profile if it exists, excluding closed profiles
121
- * @returns The agent profile or null if not found
120
+ * Retrieves the user's instructor profile if it exists
121
+ * User can have only one instructor profile which can be active or pending
122
+ * @returns The agent profile
122
123
  */
123
- async getAgentProfile() {
124
- const agents = await this.agentProfiles;
125
- return agents?.length ? agents.filter(i => i.status !== shared_1.AccountStatus.Closed)[0] : null;
124
+ async getInstructor(manager) {
125
+ manager = manager ?? instructor_entity_2.InstructorEntity.getRepository().manager;
126
+ let instructors = await manager.findBy(instructor_entity_2.InstructorEntity, { userId: this.id });
127
+ return instructors?.find(i => i.status === shared_1.AccountStatus.Active)
128
+ || instructors?.find(i => i.status === shared_1.AccountStatus.Pending);
126
129
  }
127
130
  /**
128
- * Retrieves the user's active agent profile
129
- * @returns The active agent profile or null if not found
131
+ * Get user company instructor profile
132
+ * @param company Company entity (required)
133
+ * @param manager EntityManager
134
+ * @returns CompanyInstructorEntity
130
135
  */
131
- async getActiveAgentProfile() {
132
- let agents = await this.agentProfiles;
133
- agents = agents?.filter(i => i.status === shared_1.AccountStatus.Active);
134
- return agents?.length ? agents[0] : null;
136
+ async getCompanyInstructor(company, manager) {
137
+ manager = manager ?? instructor_entity_1.CompanyInstructorEntity.getRepository().manager;
138
+ if (!company)
139
+ return;
140
+ return await manager
141
+ .createQueryBuilder(instructor_entity_1.CompanyInstructorEntity, 'ci')
142
+ .innerJoinAndSelect('ci.instructor', 'i')
143
+ .where('ci.companyId = :companyId', { companyId: company.id })
144
+ .andWhere('ci.status IN (:...statuses)', { statuses: [shared_1.AccountStatus.Active, shared_1.AccountStatus.Pending] })
145
+ .andWhere('i.userId = :userId', { userId: this.id })
146
+ .getOne();
147
+ }
148
+ async getCompanyInstructorById(id, manager) {
149
+ manager = manager ?? instructor_entity_1.CompanyInstructorEntity.getRepository().manager;
150
+ return await manager
151
+ .createQueryBuilder(instructor_entity_1.CompanyInstructorEntity, 'ci')
152
+ .innerJoinAndSelect('ci.instructor', 'i')
153
+ .where('ci.id = :id', { id })
154
+ .andWhere('i.userId = :userId', { userId: this.id })
155
+ .getOne();
156
+ }
157
+ /************************* company profile *************************/
158
+ async getCompany(companyId) {
159
+ return await company_entity_1.CompanyEntity.createQueryBuilder('c')
160
+ .innerJoin('c.instructors', 'ci')
161
+ .innerJoin('ci.instructor', 'i')
162
+ .where('c.id = :companyId', { companyId })
163
+ .andWhere('i.userId = :userId', { userId: this.id })
164
+ .getOne();
135
165
  }
136
166
  /**
137
167
  * Checks if the user belongs to a specific company.
138
168
  *
139
169
  * @param companyId - The ID of the company to check against.
170
+ * @param status - (Optional) The account status to filter by. Defaults to `AccountStatus.Active`.
140
171
  * @returns A promise that resolves to `true` if the user belongs to the specified company, otherwise `false`.
141
172
  */
142
- async belongsToCompany(companyId) {
143
- const exists = await instructor_entity_2.CompanyInstructorEntity
173
+ async belongsToCompany(companyId, status = shared_1.AccountStatus.Active) {
174
+ const exists = await instructor_entity_1.CompanyInstructorEntity
144
175
  .createQueryBuilder('ci')
145
176
  .innerJoin('ci.instructor', 'instructor')
146
177
  .where('ci.companyId = :companyId', { companyId })
147
- .andWhere('ci.status = :status', { status: shared_1.AccountStatus.Active })
178
+ .andWhere('ci.status = :status', { status })
148
179
  .andWhere('instructor.userId = :userId', { userId: this.id })
149
180
  .getCount();
150
181
  return exists > 0;
151
182
  }
183
+ /************************* profile handlers *************************/
152
184
  /**
153
- * Checks if the user has at least one active profile (student, agent, or instructor)
154
- * @returns True if the user has an active profile, false otherwise
185
+ * Delete any pending profiles of the account
155
186
  */
156
- async hasActiveProfile(manager) {
157
- const studentManager = manager ?? student_entity_1.StudentEntity.getRepository().manager;
158
- const studentExists = await studentManager.existsBy(student_entity_1.StudentEntity, {
159
- userId: this.id,
160
- status: shared_1.AccountStatus.Active
161
- });
162
- if (studentExists)
163
- return true;
164
- const agnetManager = manager ?? agent_entity_1.AgentEntity.getRepository().manager;
165
- const agentExists = await agnetManager.existsBy(agent_entity_1.AgentEntity, {
187
+ async deletePendingProfiles() {
188
+ // delete pending student profile
189
+ const pendingStudent = await student_entity_1.StudentEntity.findOneBy({
166
190
  userId: this.id,
167
- status: shared_1.AccountStatus.Active
191
+ status: shared_1.AccountStatus.Pending
168
192
  });
169
- if (agentExists)
170
- return true;
171
- const instructorManager = manager ?? instructor_entity_1.InstructorEntity.getRepository().manager;
172
- const instructorExists = await instructorManager.existsBy(instructor_entity_1.InstructorEntity, {
193
+ if (pendingStudent) {
194
+ // if the student profile is linked to at least one program, we don't delete it
195
+ // and this student profile gets completed when the user completes another onboarding
196
+ // or tries to create a new student profile and completes it
197
+ const programExists = await program_entity_1.StudentProgramEntity.existsBy({
198
+ studentId: pendingStudent.id
199
+ });
200
+ if (!programExists) {
201
+ await pendingStudent.remove();
202
+ }
203
+ }
204
+ // delete pending agent profile
205
+ const pendingAgent = await agent_entity_1.AgentEntity.findOneBy({
173
206
  userId: this.id,
174
- status: shared_1.AccountStatus.Active
207
+ status: shared_1.AccountStatus.Pending
175
208
  });
176
- if (instructorExists)
177
- return true;
178
- return;
179
- }
180
- /**
181
- * Retrieves the next active profile based on priority (Company > Agent > Student)
182
- * Used when the user removes their currently selected profile
183
- * @returns Object containing profile type and ID, or null if no active profile exists
184
- */
185
- async getNextProfile() {
186
- if (!(await this.hasActiveProfile())) {
187
- return null;
209
+ if (pendingAgent) {
210
+ await pendingAgent.remove();
188
211
  }
189
- const instructors = await instructor_entity_2.CompanyInstructorEntity
190
- .createQueryBuilder('ci')
212
+ // delete pending company entity
213
+ const pendingCompanies = await company_entity_1.CompanyEntity
214
+ .createQueryBuilder('c')
215
+ .innerJoin('c.instructors', 'ci')
191
216
  .innerJoin('ci.instructor', 'i')
192
- .where('i.userId = :userId', { userId: this.id })
193
- .andWhere('ci.status = :status', { status: shared_1.AccountStatus.Active })
217
+ .innerJoin('i.user', 'u')
218
+ .where('c.status = :status', { status: shared_1.AccountStatus.Pending })
219
+ .andWhere('ci.role = :role', { role: shared_1.Role.Owner })
220
+ .andWhere('u.id = :userId', { userId: this.id })
194
221
  .getMany();
195
- if (instructors?.length) {
196
- return {
197
- type: shared_1.ProfileType.Company,
198
- id: instructors[0].companyId
199
- };
200
- }
201
- const agent = await agent_entity_1.AgentEntity.findOneBy({
202
- userId: this.id,
203
- status: shared_1.AccountStatus.Active
204
- });
205
- if (agent) {
206
- return {
207
- type: shared_1.ProfileType.Agent,
208
- id: agent.id
209
- };
210
- }
211
- const student = await student_entity_1.StudentEntity.findOneBy({
212
- userId: this.id,
213
- status: shared_1.AccountStatus.Active
214
- });
215
- if (student) {
216
- return {
217
- type: shared_1.ProfileType.Student,
218
- id: student.id
219
- };
222
+ if (pendingCompanies?.length) {
223
+ for (const pendingCompany of pendingCompanies) {
224
+ await pendingCompany.remove();
225
+ }
220
226
  }
221
- return;
222
227
  }
228
+ /***************************** profile *****************************/
223
229
  /**
224
- * Retrieves the entity for the user's currently selected profile
225
- * @returns The selected profile entity (Student, Agent, or CompanyInstructor) or null
230
+ *
231
+ * @param device UserDeviceEntity
232
+ * @returns SelectedProfile
226
233
  */
227
- async getSelectedProfile() {
228
- switch (this.selectedProfile?.type) {
229
- case shared_1.ProfileType.Company:
230
- return await this.getSelectedInstructor();
231
- case shared_1.ProfileType.Student:
232
- return await this.getSelectedStudent();
233
- case shared_1.ProfileType.Agent:
234
- return await this.getSelectedAgent();
235
- default:
236
- return null;
237
- }
234
+ getSelectedProfile(device) {
235
+ return device?.selectedProfile ?? this.selectedProfile;
238
236
  }
239
237
  /**
240
- * Retrieves the selected student profile if currently selected
241
- * @returns The student entity or null if not selected or not found
238
+ * Reset selected profile for the user
239
+ * @param guid
240
+ * @returns UserEntity
242
241
  */
243
- async getSelectedStudent() {
244
- if (this.selectedProfile?.type !== shared_1.ProfileType.Student) {
245
- return null;
246
- }
247
- return await student_entity_1.StudentEntity.findOneBy({
248
- id: this.selectedProfile.id
249
- });
242
+ async resetSelectedProfile(guid) {
243
+ return await this.selectProfile(null, guid);
250
244
  }
251
245
  /**
252
- * Retrieves the selected agent profile if currently selected
253
- * @returns The agent entity or null if not selected or not found
246
+ * Select student profile for the user
247
+ * @param student
248
+ * @param guid
249
+ * @returns UserEntity
254
250
  */
255
- async getSelectedAgent() {
256
- if (this.selectedProfile?.type !== shared_1.ProfileType.Agent) {
257
- return null;
258
- }
259
- return await agent_entity_1.AgentEntity.findOneBy({
260
- id: this.selectedProfile.id
261
- });
251
+ async selectStudent(student, guid) {
252
+ const profile = {
253
+ type: shared_2.ProfileType.Student,
254
+ id: student.id
255
+ };
256
+ return await this.selectProfile(profile, guid);
262
257
  }
263
258
  /**
264
- * Retrieves the selected company profile if currently selected
265
- * @returns The company entity or null if not selected or not found
259
+ * Select agent profile for the user
260
+ * @param agent
261
+ * @param guid
262
+ * @returns UserEntity
266
263
  */
267
- async getSelectedCompany() {
268
- if (this.selectedProfile?.type !== shared_1.ProfileType.Company) {
269
- return null;
270
- }
271
- return await company_entity_1.CompanyEntity.findOneBy({
272
- id: this.selectedProfile.id
273
- });
264
+ async selectAgent(agent, guid) {
265
+ const profile = {
266
+ type: shared_2.ProfileType.Agent,
267
+ id: agent.id
268
+ };
269
+ return await this.selectProfile(profile, guid);
274
270
  }
275
271
  /**
276
- * Retrieves the instructor profile for the user in the currently selected company
277
- * @returns The company instructor entity or undefined if no company is selected
272
+ * Select company instructor profile for the user
273
+ * @param instructor
274
+ * @param guid
275
+ * @returns UserEntity
278
276
  */
279
- async getSelectedInstructor() {
280
- const company = await this.getSelectedCompany();
281
- if (!company)
282
- return;
283
- return await this.getInstructor(company);
277
+ async selectInstructor(instructor, guid) {
278
+ const profile = {
279
+ type: shared_2.ProfileType.Company,
280
+ id: instructor.id
281
+ };
282
+ return await this.selectProfile(profile, guid);
284
283
  }
285
284
  /**
286
- * Get the instructor profile for the user in the specified company, regardless of the profile status (pending, invited, etc...)
287
- * @param company - The company to get the instructor profile for
288
- * @returns The instructor profile for the user in the specified company
285
+ * Check if user has at least one active profile
286
+ * @param manager EntityManager
287
+ * @returns boolean
289
288
  */
290
- async getInstructor(company) {
291
- return await instructor_entity_2.CompanyInstructorEntity
292
- .createQueryBuilder('ci')
289
+ async hasActiveProfile(manager) {
290
+ manager = manager ?? UserEntity_1.getRepository().manager;
291
+ // check active student profile
292
+ const student = await this.getStudent(manager);
293
+ if (student && student.status === shared_1.AccountStatus.Active) {
294
+ return true;
295
+ }
296
+ // check active agent profile
297
+ const agent = await this.getAgent(manager);
298
+ if (agent && agent.status === shared_1.AccountStatus.Active) {
299
+ return true;
300
+ }
301
+ // check active company instructor profiles
302
+ const companyInstructorCount = await manager
303
+ .createQueryBuilder(instructor_entity_1.CompanyInstructorEntity, 'ci')
293
304
  .innerJoin('ci.instructor', 'i')
294
- .where('ci.companyId = :companyId', { companyId: company.id })
295
- .andWhere('i.userId = :userId', { userId: this.id })
296
- .getOne();
297
- }
298
- /**
299
- * Remove suffix from phone number if the account is closed
300
- * @returns phone number that should be returned to ui
301
- */
302
- getPhone() {
303
- return (this.status === shared_1.AccountStatus.Closed ?
304
- this.phone.includes('-') ?
305
- this.phone.split('-')[0]
306
- : this.phone
307
- : this.phone);
308
- }
309
- hasPushNotificationsEnabled() {
310
- return this.fcmTokens && this.fcmTokens.length > 0;
305
+ .where('i.userId = :userId', { userId: this.id })
306
+ .andWhere('ci.status = :status', { status: shared_1.AccountStatus.Active })
307
+ .getCount();
308
+ if (companyInstructorCount > 0) {
309
+ return true;
310
+ }
311
+ return false;
311
312
  }
312
313
  /**
313
- * Get the pending company profile for the user
314
+ * Select next active profile for the user
315
+ * @param guid Device guid
316
+ * @returns true if a profile was selected, false otherwise
314
317
  */
315
- async getPendingCompany(manager) {
316
- const companyManager = manager ?? company_entity_1.CompanyEntity.getRepository().manager;
317
- return await companyManager
318
- .createQueryBuilder(company_entity_1.CompanyEntity, 'c')
319
- .innerJoin('c.instructors', 'ci')
320
- .innerJoin('ci.instructor', 'i')
321
- .innerJoin('i.user', 'u')
322
- .where('c.status = :status', { status: shared_1.AccountStatus.Pending })
323
- .andWhere('ci.role = :role', { role: shared_1.Role.Owner })
324
- .andWhere('u.id = :userId', { userId: this.id })
325
- .getOne();
318
+ async selectNextActiveProfile(guid) {
319
+ const companyInstructors = await instructor_entity_1.CompanyInstructorEntity
320
+ .createQueryBuilder('ci')
321
+ .innerJoin('ci.instructor', 'instructor')
322
+ .where('instructor.userId = :userId', { userId: this.id })
323
+ .andWhere('ci.status = :status', { status: shared_1.AccountStatus.Active })
324
+ .orderBy('ci.createdOn', 'DESC')
325
+ .getMany();
326
+ if (companyInstructors?.length) {
327
+ // select first matched company instructor
328
+ const companyInstructor = companyInstructors[0];
329
+ await this.selectInstructor(companyInstructor, guid);
330
+ return { type: shared_2.ProfileType.Company, id: companyInstructor.id };
331
+ }
332
+ const student = await this.getStudent();
333
+ if (student && student.status === shared_1.AccountStatus.Active) {
334
+ await this.selectStudent(student, guid);
335
+ return { type: shared_2.ProfileType.Student, id: student.id };
336
+ }
337
+ const agent = await this.getAgent();
338
+ if (agent && agent.status === shared_1.AccountStatus.Active) {
339
+ await this.selectAgent(agent, guid);
340
+ return { type: shared_2.ProfileType.Agent, id: agent.id };
341
+ }
342
+ return;
326
343
  }
327
344
  /**
328
- * Get the pending student profile for the user
329
- * @param manager EntityManager - optional transaction manager to use in a transaction
345
+ * Helper to select profile and update device if guid provided
346
+ * @param profile
347
+ * @param guid
348
+ * @returns UserEntity
330
349
  */
331
- async getPendingStudent(manager) {
332
- const studentManager = manager ?? student_entity_1.StudentEntity.getRepository().manager;
333
- return await studentManager.findOneBy(student_entity_1.StudentEntity, {
334
- status: shared_1.AccountStatus.Pending,
335
- userId: this.id
336
- });
350
+ async selectProfile(profile, guid) {
351
+ if (guid) {
352
+ const device = await device_entity_1.UserDeviceEntity.findOneBy({ guid, userId: this.id });
353
+ if (device) {
354
+ device.selectedProfile = profile;
355
+ await device.save();
356
+ }
357
+ }
358
+ this.selectedProfile = profile;
359
+ return await this.save();
337
360
  }
361
+ /***************************** activities *****************************/
338
362
  /**
339
- * Get the pending agent profile for the user
363
+ * Check if user last activity is overdated
364
+ * @returns
340
365
  */
341
- async getPendingAgent(manager) {
342
- const agentManager = manager ?? agent_entity_1.AgentEntity.getRepository().manager;
343
- return await agentManager.findOneBy(agent_entity_1.AgentEntity, {
344
- status: shared_1.AccountStatus.Pending,
345
- userId: this.id
346
- });
366
+ isActivityOverdated(days = 180) {
367
+ if (!this.lastActivity) {
368
+ return;
369
+ }
370
+ // the beginning of the time, before which the activity is considered overdated
371
+ const startDate = luxon_1.DateTime.now().minus({ days }).toJSDate();
372
+ // go back 180 days from now
373
+ return this.lastActivity < startDate;
347
374
  }
348
375
  /**
349
- * Delete any pending profiles of the account
376
+ * Updates the last activity timestamp of the user to the current date and saves it.
377
+ * Used to track when the user was last active in the system.
378
+ * @returns The updated user entity
350
379
  */
351
- async deletePendingProfiles() {
352
- // TODO: implement cascade delete on orphanedRowAction for OneToMany relations, and some of the OneToOne relations
353
- // delete pending student profile
354
- const pendingStudent = await this.getPendingStudent();
355
- if (pendingStudent) {
356
- // if the student profile is linked to at least one program, we don't delete it
357
- // and this student profile gets completed when the user completes another onboarding
358
- // or tries to create a new student profile and completes it
359
- const programExists = await program_entity_1.StudentProgramEntity.existsBy({
360
- studentId: pendingStudent.id
361
- });
362
- if (!programExists) {
363
- await pendingStudent.remove();
364
- }
365
- }
366
- // delete pending agent profile
367
- const pendingAgent = await this.getPendingAgent();
368
- await pendingAgent?.remove();
369
- // delete pending company entity
370
- const pendingCompany = await this.getPendingCompany();
371
- await pendingCompany?.remove();
380
+ async updateActivity() {
381
+ this.lastActivity = new Date();
382
+ return await this.save();
372
383
  }
373
384
  /**
374
385
  * Retrieves all tracked activities for this user (creation and update timestamps)
@@ -376,22 +387,11 @@ let UserEntity = UserEntity_1 = class UserEntity extends trackable_1.TrackableEn
376
387
  */
377
388
  async getActivities() {
378
389
  const activities = [];
379
- activities.push(await (0, activity_helper_1.toActivity)(this.createdBy, this.createdOn, shared_1.ActivityType.created));
380
- activities.push(await (0, activity_helper_1.toActivity)(this.updatedBy, this.updatedOn, shared_1.ActivityType.updated));
390
+ activities.push(await (0, activity_helper_1.toActivity)(this.createdBy, this.createdOn, shared_2.ActivityType.created));
391
+ activities.push(await (0, activity_helper_1.toActivity)(this.updatedBy, this.updatedOn, shared_2.ActivityType.updated));
381
392
  return activities.filter(a => a);
382
393
  }
383
- getProfileName() {
384
- if (!this.selectedProfile?.type)
385
- return '';
386
- const i18n = nestjs_i18n_1.I18nContext.current();
387
- return i18n.t(`general.profileType.${this.selectedProfile.type}`);
388
- }
389
- getLanguageName() {
390
- if (!this.language)
391
- return '';
392
- const i18n = nestjs_i18n_1.I18nContext.current();
393
- return i18n.t(`general.languages.${this.language}`);
394
- }
394
+ /***************************** logs *****************************/
395
395
  /**
396
396
  * Log user event
397
397
  * @param event Event type
@@ -488,24 +488,8 @@ __decorate([
488
488
  nullable: true,
489
489
  default: null
490
490
  }),
491
- __metadata("design:type", common_1.Address)
491
+ __metadata("design:type", shared_1.Address)
492
492
  ], UserEntity.prototype, "address", void 0);
493
- __decorate([
494
- (0, typeorm_1.Column)({
495
- type: 'simple-json',
496
- nullable: true,
497
- default: null
498
- }),
499
- __metadata("design:type", Object)
500
- ], UserEntity.prototype, "selectedProfile", void 0);
501
- __decorate([
502
- (0, typeorm_1.Column)({
503
- type: 'simple-json',
504
- nullable: true,
505
- default: null
506
- }),
507
- __metadata("design:type", Array)
508
- ], UserEntity.prototype, "fcmTokens", void 0);
509
493
  __decorate([
510
494
  (0, typeorm_1.Column)({
511
495
  nullable: true,
@@ -521,6 +505,20 @@ __decorate([
521
505
  }),
522
506
  __metadata("design:type", String)
523
507
  ], UserEntity.prototype, "timezone", void 0);
508
+ __decorate([
509
+ (0, typeorm_1.Column)({
510
+ default: false
511
+ }),
512
+ __metadata("design:type", Boolean)
513
+ ], UserEntity.prototype, "identityConfirmed", void 0);
514
+ __decorate([
515
+ (0, typeorm_1.Column)({
516
+ type: 'simple-json',
517
+ nullable: true,
518
+ default: null
519
+ }),
520
+ __metadata("design:type", Object)
521
+ ], UserEntity.prototype, "selectedProfile", void 0);
524
522
  __decorate([
525
523
  (0, typeorm_1.Column)({
526
524
  nullable: true,
@@ -537,9 +535,13 @@ __decorate([
537
535
  __metadata("design:type", Promise)
538
536
  ], UserEntity.prototype, "agentProfiles", void 0);
539
537
  __decorate([
540
- (0, typeorm_1.OneToMany)(() => instructor_entity_1.InstructorEntity, instructor => instructor.user),
538
+ (0, typeorm_1.OneToMany)(() => instructor_entity_2.InstructorEntity, instructor => instructor.user),
541
539
  __metadata("design:type", Promise)
542
540
  ], UserEntity.prototype, "instructorProfiles", void 0);
541
+ __decorate([
542
+ (0, typeorm_1.OneToMany)(() => instructor_entity_1.CompanyInstructorEntity, instructor => instructor.user),
543
+ __metadata("design:type", Promise)
544
+ ], UserEntity.prototype, "companyInstructors", void 0);
543
545
  __decorate([
544
546
  (0, typeorm_1.ManyToOne)(() => country_entity_1.CountryEntity, country => country.users),
545
547
  __metadata("design:type", Promise)