@driveup/schema 0.2.5 → 0.2.7

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