@tomei/rental 0.12.0 → 0.12.2

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 (136) hide show
  1. package/.commitlintrc.json +22 -22
  2. package/.eslintrc +16 -16
  3. package/.eslintrc.js +35 -35
  4. package/.gitlab-ci.yml +16 -16
  5. package/.husky/commit-msg +15 -15
  6. package/.husky/pre-commit +7 -7
  7. package/.prettierrc +4 -4
  8. package/Jenkinsfile +51 -51
  9. package/README.md +8 -8
  10. package/dist/index.d.ts +1 -1
  11. package/dist/index.js +17 -17
  12. package/dist/src/components/agreement/agreement.d.ts +17 -17
  13. package/dist/src/components/agreement/agreement.js +49 -49
  14. package/dist/src/components/agreement/agreement.js.map +1 -1
  15. package/dist/src/components/agreement/agreement.repository.d.ts +8 -8
  16. package/dist/src/components/agreement/agreement.repository.js +66 -66
  17. package/dist/src/components/agreement/agreement.repository.js.map +1 -1
  18. package/dist/src/components/booking/booking.d.ts +46 -46
  19. package/dist/src/components/booking/booking.js +313 -313
  20. package/dist/src/components/booking/booking.js.map +1 -1
  21. package/dist/src/components/booking/booking.repository.d.ts +8 -8
  22. package/dist/src/components/booking/booking.repository.js +66 -66
  23. package/dist/src/components/booking/booking.repository.js.map +1 -1
  24. package/dist/src/components/joint-hirer/joint-hirer.d.ts +23 -23
  25. package/dist/src/components/joint-hirer/joint-hirer.js +105 -105
  26. package/dist/src/components/joint-hirer/joint-hirer.js.map +1 -1
  27. package/dist/src/components/joint-hirer/joint-hirer.repository.d.ts +8 -8
  28. package/dist/src/components/joint-hirer/joint-hirer.repository.js +66 -66
  29. package/dist/src/components/joint-hirer/joint-hirer.repository.js.map +1 -1
  30. package/dist/src/components/rental/rental.d.ts +59 -59
  31. package/dist/src/components/rental/rental.js +618 -618
  32. package/dist/src/components/rental/rental.js.map +1 -1
  33. package/dist/src/components/rental/rental.repository.d.ts +8 -8
  34. package/dist/src/components/rental/rental.repository.js +66 -66
  35. package/dist/src/components/rental/rental.repository.js.map +1 -1
  36. package/dist/src/components/rental-price/rental-price.d.ts +18 -18
  37. package/dist/src/components/rental-price/rental-price.js +78 -78
  38. package/dist/src/components/rental-price/rental-price.js.map +1 -1
  39. package/dist/src/components/rental-price/rental-price.repository.d.ts +8 -8
  40. package/dist/src/components/rental-price/rental-price.repository.js +66 -66
  41. package/dist/src/components/rental-price/rental-price.repository.js.map +1 -1
  42. package/dist/src/database.d.ts +4 -4
  43. package/dist/src/database.js +24 -25
  44. package/dist/src/database.js.map +1 -1
  45. package/dist/src/enum/account-type.enum.d.ts +4 -4
  46. package/dist/src/enum/account-type.enum.js +8 -8
  47. package/dist/src/enum/account-type.enum.js.map +1 -1
  48. package/dist/src/enum/aggrement-status.enum.d.ts +5 -5
  49. package/dist/src/enum/aggrement-status.enum.js +9 -9
  50. package/dist/src/enum/aggrement-status.enum.js.map +1 -1
  51. package/dist/src/enum/booking.enum.d.ts +5 -5
  52. package/dist/src/enum/booking.enum.js +9 -9
  53. package/dist/src/enum/booking.enum.js.map +1 -1
  54. package/dist/src/enum/index.d.ts +5 -5
  55. package/dist/src/enum/index.js +11 -11
  56. package/dist/src/enum/rental-status.enum.d.ts +9 -9
  57. package/dist/src/enum/rental-status.enum.js +13 -13
  58. package/dist/src/enum/rental-status.enum.js.map +1 -1
  59. package/dist/src/index.d.ts +15 -15
  60. package/dist/src/index.js +42 -42
  61. package/dist/src/interfaces/agreement-attr.interface.d.ts +7 -7
  62. package/dist/src/interfaces/agreement-attr.interface.js +2 -2
  63. package/dist/src/interfaces/booking-attr.interface.d.ts +18 -18
  64. package/dist/src/interfaces/booking-attr.interface.js +2 -2
  65. package/dist/src/interfaces/booking-find-all-search-attr.interface.d.ts +12 -12
  66. package/dist/src/interfaces/booking-find-all-search-attr.interface.js +2 -2
  67. package/dist/src/interfaces/index.d.ts +7 -7
  68. package/dist/src/interfaces/index.js +2 -2
  69. package/dist/src/interfaces/joint-hirer-attr.interface.d.ts +10 -10
  70. package/dist/src/interfaces/joint-hirer-attr.interface.js +2 -2
  71. package/dist/src/interfaces/rental-attr.interface.d.ts +24 -24
  72. package/dist/src/interfaces/rental-attr.interface.js +2 -2
  73. package/dist/src/interfaces/rental-find-all-search-attr.interface.d.ts +10 -10
  74. package/dist/src/interfaces/rental-find-all-search-attr.interface.js +2 -2
  75. package/dist/src/interfaces/rental-price-attr.interface.d.ts +7 -7
  76. package/dist/src/interfaces/rental-price-attr.interface.js +2 -2
  77. package/dist/src/models/agreement.entity.d.ts +10 -10
  78. package/dist/src/models/agreement.entity.js +59 -59
  79. package/dist/src/models/agreement.entity.js.map +1 -1
  80. package/dist/src/models/booking.entity.d.ts +21 -21
  81. package/dist/src/models/booking.entity.js +127 -127
  82. package/dist/src/models/booking.entity.js.map +1 -1
  83. package/dist/src/models/index.d.ts +6 -6
  84. package/dist/src/models/index.js +13 -13
  85. package/dist/src/models/joint-hirer.entity.d.ts +13 -13
  86. package/dist/src/models/joint-hirer.entity.js +78 -78
  87. package/dist/src/models/joint-hirer.entity.js.map +1 -1
  88. package/dist/src/models/rental-price.entity.d.ts +8 -8
  89. package/dist/src/models/rental-price.entity.js +58 -58
  90. package/dist/src/models/rental-price.entity.js.map +1 -1
  91. package/dist/src/models/rental.entity.d.ts +29 -29
  92. package/dist/src/models/rental.entity.js +159 -159
  93. package/dist/src/models/rental.entity.js.map +1 -1
  94. package/dist/tsconfig.tsbuildinfo +1 -1
  95. package/eslint.config.mjs +37 -0
  96. package/jest.config.js +10 -10
  97. package/migrations/booking-table-migration.js +79 -79
  98. package/migrations/joint-hirer-table-migration.js +52 -52
  99. package/migrations/rental-aggrement-table-migration.js +30 -30
  100. package/migrations/rental-price-table-migration.js +32 -32
  101. package/migrations/rental-table-migrations.js +96 -96
  102. package/package.json +78 -75
  103. package/sonar-project.properties +12 -12
  104. package/src/components/agreement/agreement.repository.ts +54 -54
  105. package/src/components/agreement/agreement.ts +49 -49
  106. package/src/components/booking/booking.repository.ts +51 -51
  107. package/src/components/booking/booking.ts +492 -492
  108. package/src/components/joint-hirer/joint-hirer.repository.ts +54 -54
  109. package/src/components/joint-hirer/joint-hirer.ts +1 -1
  110. package/src/components/rental/rental.repository.ts +51 -51
  111. package/src/components/rental/rental.ts +963 -966
  112. package/src/components/rental-price/rental-price.repository.ts +54 -54
  113. package/src/components/rental-price/rental-price.ts +100 -100
  114. package/src/database.ts +27 -27
  115. package/src/enum/account-type.enum.ts +4 -4
  116. package/src/enum/booking.enum.ts +5 -5
  117. package/src/enum/index.ts +11 -11
  118. package/src/enum/rental-status.enum.ts +39 -39
  119. package/src/index.ts +28 -28
  120. package/src/interfaces/agreement-attr.interface.ts +7 -7
  121. package/src/interfaces/booking-attr.interface.ts +19 -19
  122. package/src/interfaces/booking-find-all-search-attr.interface.ts +12 -12
  123. package/src/interfaces/index.ts +15 -15
  124. package/src/interfaces/joint-hirer-attr.interface.ts +10 -10
  125. package/src/interfaces/rental-attr.interface.ts +25 -25
  126. package/src/interfaces/rental-find-all-search-attr.interface.ts +11 -11
  127. package/src/interfaces/rental-price-attr.interface.ts +7 -7
  128. package/src/models/agreement.entity.ts +39 -39
  129. package/src/models/booking.entity.ts +105 -105
  130. package/src/models/index.ts +13 -13
  131. package/src/models/joint-hirer.entity.ts +63 -63
  132. package/src/models/rental-price.entity.ts +38 -38
  133. package/src/models/rental.entity.ts +133 -133
  134. package/tsconfig.build.json +5 -5
  135. package/tsconfig.json +23 -23
  136. package/.eslintignore +0 -1
@@ -1,966 +1,963 @@
1
- import { IRentalAttr } from '../../interfaces/rental-attr.interface';
2
- import { RentalStatusEnum } from '../../enum/rental-status.enum';
3
- import { RentalRepository } from './rental.repository';
4
- import { ClassError, ObjectBase } from '@tomei/general';
5
- import { ApplicationConfig } from '@tomei/config';
6
- import { LoginUser } from '@tomei/sso';
7
- import { RentalPrice } from '../rental-price/rental-price';
8
- import { Op, QueryTypes } from 'sequelize';
9
- import { ActionEnum, Activity } from '@tomei/activity-history';
10
- import { IRentalFindAllSearchAttr } from '../../interfaces/rental-find-all-search-attr.interface';
11
- import { RentalAccountTypeEnum } from '../../enum/account-type.enum';
12
- import { JointHirer } from '../joint-hirer/joint-hirer';
13
- import { JointHirerModel } from '../../models/joint-hirer.entity';
14
- import { AgreementRepository } from '../agreement/agreement.repository';
15
- import * as rentalDb from '../../database';
16
- import { RentalModel } from '../../models/rental.entity';
17
- import { JointHirerRepository } from '../joint-hirer/joint-hirer.repository';
18
- import { AgreementModel } from '../../models';
19
- import { Agreement } from '../agreement/agreement';
20
- import { AggrementStatusEnum } from '../../enum/aggrement-status.enum';
21
-
22
- export class Rental extends ObjectBase {
23
- ObjectId: string;
24
- ObjectName: string;
25
- ObjectType = 'Rental';
26
- TableName: string;
27
- CustomerId: string;
28
- CustomerType: string;
29
- ItemId: string;
30
- ItemType: string;
31
- PriceId: string;
32
- StartDateTime: Date;
33
- EndDateTime: Date;
34
- CancelRemarks: string;
35
- TerminateRemarks: string;
36
- AgreementNo: string;
37
- AccountType: RentalAccountTypeEnum;
38
- JointHirers: JointHirer[] = [];
39
- protected _Status: RentalStatusEnum;
40
- protected _EscheatmentYN: string = 'N';
41
- protected _CreatedById: string;
42
- protected _CreatedAt: Date;
43
- protected _UpdatedById: string;
44
- protected _UpdatedAt: Date;
45
- protected static _Repo = new RentalRepository();
46
- protected static _AgreementRepo = new AgreementRepository();
47
- protected static _JointHirerRepo = new JointHirerRepository();
48
-
49
- get RentalId(): string {
50
- return this.ObjectId;
51
- }
52
-
53
- set RentalId(value: string) {
54
- this.ObjectId = value;
55
- }
56
-
57
- get Status(): RentalStatusEnum {
58
- return this._Status;
59
- }
60
-
61
- get EscheatmentYN(): string {
62
- return this._EscheatmentYN;
63
- }
64
-
65
- get CreatedById(): string {
66
- return this._CreatedById;
67
- }
68
-
69
- get CreatedAt(): Date {
70
- return this._CreatedAt;
71
- }
72
-
73
- get UpdatedById(): string {
74
- return this._UpdatedById;
75
- }
76
-
77
- get UpdatedAt(): Date {
78
- return this._UpdatedAt;
79
- }
80
-
81
- private setTerminated() {
82
- this._Status = RentalStatusEnum.TERMINATED;
83
- }
84
-
85
- protected constructor(rentalAttr?: IRentalAttr) {
86
- super();
87
- if (rentalAttr) {
88
- this.RentalId = rentalAttr.RentalId;
89
- this.CustomerId = rentalAttr.CustomerId;
90
- this.CustomerType = rentalAttr.CustomerType;
91
- this.ItemId = rentalAttr.ItemId;
92
- this.ItemType = rentalAttr.ItemType;
93
- this.PriceId = rentalAttr.PriceId;
94
- this.StartDateTime = rentalAttr.StartDateTime;
95
- this.EndDateTime = rentalAttr.EndDateTime;
96
- this.CancelRemarks = rentalAttr.CancelRemarks;
97
- this.TerminateRemarks = rentalAttr.TerminateRemarks;
98
- this.AgreementNo = rentalAttr.AgreementNo;
99
- this.AccountType = rentalAttr.AccountType;
100
- this._Status = rentalAttr.Status;
101
- this._EscheatmentYN = rentalAttr.EscheatmentYN;
102
- this._CreatedById = rentalAttr.CreatedById;
103
- this._CreatedAt = rentalAttr.CreatedAt;
104
- this._UpdatedById = rentalAttr.UpdatedById;
105
- this._UpdatedAt = rentalAttr.UpdatedAt;
106
- }
107
- }
108
-
109
- public static async init(dbTransaction?: any, rentalId?: string) {
110
- try {
111
- if (rentalId) {
112
- const rental = await Rental._Repo.findByPk(rentalId, dbTransaction);
113
- if (rental) {
114
- return new Rental(rental);
115
- } else {
116
- throw new ClassError('Rental', 'RentalErrMsg00', 'Rental Not Found');
117
- }
118
- }
119
- return new Rental();
120
- } catch (error) {
121
- throw new ClassError(
122
- 'Rental',
123
- 'RentalErrMsg00',
124
- 'Failed To Initialize Price',
125
- );
126
- }
127
- }
128
-
129
- /**
130
- * Create a new Rental record.
131
- * @param {RentalPrice} rentalPrice - The rental pricing information.
132
- * @param {LoginUser} loginUser - The user initiating the creation.
133
- * @param {any} [dbTransaction] - Optional database transaction for atomic operations.
134
- * @throws {ClassError} Throws an error if:
135
- * 1. loginUser does not have 'Rental - Create' privilege.
136
- * 2. Rental item is not available at the current date.
137
- * @returns {Promise<any>} A Promise resolving to the created rental record.
138
- */
139
- public async create(
140
- rentalPrice: RentalPrice,
141
- loginUser: LoginUser,
142
- jointHirers?: JointHirer[],
143
- dbTransaction?: any,
144
- ): Promise<any> {
145
- try {
146
- /*Part 1: Check Privilege*/
147
- const systemCode =
148
- ApplicationConfig.getComponentConfigValue('system-code');
149
- const isPrivileged = await loginUser.checkPrivileges(
150
- systemCode,
151
- 'Rental - Create',
152
- );
153
-
154
- if (!isPrivileged) {
155
- throw new ClassError(
156
- 'Rental',
157
- 'RentalErrMsg01',
158
- "You do not have 'Rental - Create' privilege.",
159
- );
160
- }
161
-
162
- /*Part 2: Make Sure Rental Item Available*/
163
- const isItemAvailable = await Rental.isItemAvailable(
164
- this.ItemId,
165
- this.ItemType,
166
- this.StartDateTime,
167
- this.EndDateTime,
168
- dbTransaction,
169
- );
170
-
171
- if (!isItemAvailable) {
172
- throw new ClassError(
173
- 'Rental',
174
- 'RentalErrMsg02',
175
- 'Rental Item is not available at current date.',
176
- );
177
- }
178
-
179
- // Part 3: Create Rental Agreement Record
180
- // Call Rental._AgreementRepo create method by passing:
181
- // AgreementNo: this.AgreementNo
182
- // Status: "Not Generated"
183
- // dbTransaction
184
- await Rental._AgreementRepo.create(
185
- {
186
- AgreementNo: this.AgreementNo,
187
- Status: 'Not Generated',
188
- },
189
- {
190
- transaction: dbTransaction,
191
- },
192
- );
193
-
194
- /*Part 4: Insert Rental & The Agreed Rental Price*/
195
- if (!rentalPrice.PriceId) {
196
- const rentalPriceData = await rentalPrice.create(
197
- loginUser,
198
- dbTransaction,
199
- );
200
- this.PriceId = rentalPriceData.PriceId;
201
- } else {
202
- this.PriceId = rentalPrice.PriceId;
203
- }
204
- this.RentalId = this.createId();
205
- // if (!this.Status) {
206
- this._Status = RentalStatusEnum.PENDING_SIGNING;
207
- // }
208
- this._CreatedById = loginUser.ObjectId;
209
- this._UpdatedById = loginUser.ObjectId;
210
- this._CreatedAt = new Date();
211
- this._UpdatedAt = new Date();
212
-
213
- const data = {
214
- RentalId: this.RentalId,
215
- CustomerId: this.CustomerId,
216
- CustomerType: this.CustomerType,
217
- ItemId: this.ItemId,
218
- ItemType: this.ItemType,
219
- PriceId: this.PriceId,
220
- StartDateTime: this.StartDateTime,
221
- EndDateTime: this.EndDateTime,
222
- CancelRemarks: this.CancelRemarks,
223
- TerminateRemarks: this.TerminateRemarks,
224
- AgreementNo: this.AgreementNo,
225
- AccountType: this.AccountType,
226
- Status: this.Status,
227
- EscheatmentYN: this.EscheatmentYN,
228
- CreatedById: this.CreatedById,
229
- CreatedAt: this.CreatedAt,
230
- UpdatedById: this.UpdatedById,
231
- UpdatedAt: this.UpdatedAt,
232
- };
233
-
234
- await Rental._Repo.create(data, {
235
- transaction: dbTransaction,
236
- });
237
-
238
- //For every data inside Param.jointHirers, update the rentalId and call jointHirer.create
239
- if (jointHirers) {
240
- for (let i = 0; i < jointHirers.length; i++) {
241
- jointHirers[i].RentalId = this.RentalId;
242
- await jointHirers[i].create(loginUser, dbTransaction);
243
- this.JointHirers.push(jointHirers[i]);
244
- }
245
- }
246
-
247
- /*Part 5: Record Create Rental Activity*/
248
- const activity = new Activity();
249
- activity.ActivityId = activity.createId();
250
- activity.Action = ActionEnum.ADD;
251
- activity.Description = 'Add Rental';
252
- activity.EntityType = 'Rental';
253
- activity.EntityId = this.RentalId;
254
- activity.EntityValueBefore = JSON.stringify({});
255
- activity.EntityValueAfter = JSON.stringify(data);
256
- await activity.create(loginUser.ObjectId, dbTransaction);
257
-
258
- /*Part 6: Return Result*/
259
- return this;
260
- } catch (error) {
261
- throw error;
262
- }
263
- }
264
-
265
- public static async isItemAvailable(
266
- itemId: string,
267
- itemType: string,
268
- startDateTime: Date,
269
- endDateTime: Date,
270
- dbTransaction?: any,
271
- ) {
272
- try {
273
- const item = await Rental._Repo.findOne({
274
- where: {
275
- ItemId: itemId,
276
- ItemType: itemType,
277
- StartDateTime: {
278
- [Op.lte]: endDateTime,
279
- },
280
- EndDateTime: {
281
- [Op.gte]: startDateTime,
282
- },
283
- },
284
- transaction: dbTransaction,
285
- });
286
-
287
- if (item) {
288
- return false;
289
- } else {
290
- return true;
291
- }
292
- } catch (error) {
293
- throw error;
294
- }
295
- }
296
-
297
- public static async findAll(
298
- loginUser: LoginUser,
299
- dbTransaction: any,
300
- page?: number,
301
- row?: number,
302
- search?: IRentalFindAllSearchAttr,
303
- ) {
304
- try {
305
- const systemCode = await ApplicationConfig.getComponentConfigValue(
306
- 'system-code',
307
- );
308
-
309
- const isPrivileged = await loginUser.checkPrivileges(
310
- systemCode,
311
- 'Rental - View',
312
- );
313
-
314
- if (!isPrivileged) {
315
- throw new ClassError(
316
- 'Rental',
317
- 'RentalErrMsg01',
318
- "You do not have 'Rental - View' privilege.",
319
- );
320
- }
321
-
322
- const queryObj: any = {};
323
-
324
- let options: any = {
325
- transaction: dbTransaction,
326
- order: [['CreatedAt', 'DESC']],
327
- };
328
-
329
- if (page && row) {
330
- options = {
331
- ...options,
332
- limit: row,
333
- offset: row * (page - 1),
334
- };
335
- }
336
-
337
- if (search) {
338
- Object.entries(search).forEach(([key, value]) => {
339
- if (key === 'StartDateTime') {
340
- queryObj[key] = {
341
- [Op.gte]: value,
342
- };
343
- } else if (key === 'EndDateTime') {
344
- queryObj[key] = {
345
- [Op.lte]: value,
346
- };
347
- } else if (key === 'CustomerId') {
348
- queryObj[key] = {
349
- [Op.substring]: value,
350
- };
351
-
352
- options.include = [
353
- {
354
- model: JointHirerModel,
355
- required: false,
356
- where: {
357
- CustomerId: {
358
- [Op.substring]: value,
359
- },
360
- },
361
- },
362
- ];
363
- } else {
364
- queryObj[key] = {
365
- [Op.substring]: value,
366
- };
367
- }
368
- });
369
- if (options?.include?.length > 1) {
370
- options.include.push({
371
- model: AgreementModel,
372
- required: false,
373
- });
374
- } else {
375
- options.include = [
376
- {
377
- model: AgreementModel,
378
- required: false,
379
- },
380
- ];
381
- }
382
-
383
- options = {
384
- ...options,
385
- where: queryObj,
386
- };
387
- }
388
-
389
- return await Rental._Repo.findAndCountAll(options);
390
- } catch (err) {
391
- throw err;
392
- }
393
- }
394
-
395
- public static async checkActiveByItemId(
396
- loginUser: LoginUser,
397
- itemId: string,
398
- itemType: string,
399
- dbTransaction?: any,
400
- ) {
401
- try {
402
- const systemCode = await ApplicationConfig.getComponentConfigValue(
403
- 'system-code',
404
- );
405
-
406
- const isPrivileged = await loginUser.checkPrivileges(
407
- systemCode,
408
- 'Rental - View',
409
- );
410
-
411
- if (!isPrivileged) {
412
- throw new ClassError(
413
- 'Rental',
414
- 'RentalErrMsg01',
415
- "You do not have 'Rental - View' privilege.",
416
- );
417
- }
418
-
419
- const queryObj: any = {
420
- ItemId: itemId,
421
- ItemType: itemType,
422
- Status: RentalStatusEnum.ACTIVE,
423
- };
424
-
425
- const options: any = {
426
- transaction: dbTransaction,
427
- where: queryObj,
428
- };
429
-
430
- const rental = await Rental._Repo.findOne(options);
431
-
432
- if (rental) {
433
- return true;
434
- } else {
435
- return false;
436
- }
437
- } catch (err) {
438
- throw err;
439
- }
440
- }
441
-
442
- /**
443
- * Sets the StartDateTime property of the Rental class as custom setter.
444
- * @param {Date} startDateTime - The start date and time of the rental.
445
- * @throws {ClassError} Throws an error if:
446
- * 1. startDateTime is a past date.
447
- * 2. startDateTime is more than the EndDateTime.
448
- * @returns {void}
449
- */
450
- setStartDateTime(startDateTime: Date): void {
451
- const startDateTimeObject = new Date(startDateTime);
452
- startDateTimeObject.setHours(0, 0, 0, 0);
453
-
454
- /*Part 1: Make Sure Future Date Time*/
455
- if (startDateTimeObject < new Date(new Date().setHours(0, 0, 0, 0))) {
456
- throw new ClassError(
457
- 'Rental',
458
- 'RentalErrMsg02',
459
- 'StartDateTime cannot be a past datetime.',
460
- );
461
- }
462
-
463
- /*Part 2: Make Sure Less Than End Date Time*/
464
- if (this.EndDateTime && startDateTimeObject > this.EndDateTime) {
465
- throw new ClassError(
466
- 'Rental',
467
- 'RentalErrMsg03',
468
- 'StartDateTime cannot be more than EndDateTime.',
469
- );
470
- }
471
-
472
- /*Part 3: Set Status Whether Reserved or Active*/
473
- if (startDateTimeObject > new Date(new Date().setHours(0, 0, 0, 0))) {
474
- this._Status = RentalStatusEnum.RESERVED;
475
- } else {
476
- this._Status = RentalStatusEnum.ACTIVE;
477
- }
478
- }
479
-
480
- public async periodEndProcess(
481
- loginUser: LoginUser,
482
- dbTransaction: any,
483
- stockInventory: any,
484
- ) {
485
- try {
486
- // Privilege Checking
487
- const systemCode = await ApplicationConfig.getComponentConfigValue(
488
- 'system-code',
489
- );
490
-
491
- const isPrivileged = await loginUser.checkPrivileges(
492
- systemCode,
493
- 'Rental PeriodEndProcess',
494
- );
495
-
496
- if (!isPrivileged) {
497
- throw new ClassError(
498
- 'Rental',
499
- 'RentalErrMsg04',
500
- "You do not have 'Rental - PeriodEndProcess' privilege.",
501
- );
502
- }
503
-
504
- // Validate Existing Rental
505
- if (this.AgreementNo === undefined || this.AgreementNo === null) {
506
- throw new ClassError(
507
- 'Rental',
508
- 'RentalErrMsg05',
509
- 'Rental must be existing rental.',
510
- );
511
- }
512
-
513
- // Validate Rental End Period
514
- if (this.EndDateTime === new Date(new Date().setHours(0, 0, 0, 0))) {
515
- throw new ClassError(
516
- 'Rental',
517
- 'RentalErrMsg06',
518
- 'Rental period is not ending today.',
519
- );
520
- }
521
-
522
- // Mark Rental Item as Available
523
- await stockInventory.setAvailable(loginUser, dbTransaction);
524
-
525
- // Capture Record Info Before Changes
526
- const entityValueBefore = {
527
- RentalId: this.RentalId,
528
- CustomerId: this.CustomerId,
529
- CustomerType: this.CustomerType,
530
- ItemId: this.ItemId,
531
- ItemType: this.ItemType,
532
- PriceId: this.PriceId,
533
- StartDateTime: this.StartDateTime,
534
- EndDateTime: this.EndDateTime,
535
- CancelRemarks: this.CancelRemarks,
536
- TerminateRemarks: this.TerminateRemarks,
537
- AgreementNo: this.AgreementNo,
538
- AccountType: this.AccountType,
539
- Status: this.Status,
540
- EscheatmentYN: this.EscheatmentYN,
541
- CreatedById: this.CreatedById,
542
- CreatedAt: this.CreatedAt,
543
- UpdatedById: this.UpdatedById,
544
- UpdatedAt: this.UpdatedAt,
545
- };
546
-
547
- // Mark Rental as Terminated and Capture Updater Info
548
- this.setTerminated();
549
- this._UpdatedById = loginUser.ObjectId;
550
- this._UpdatedAt = new Date();
551
-
552
- // Capture Record Info after Changes
553
- const entityValueAfter = {
554
- RentalId: this.RentalId,
555
- CustomerId: this.CustomerId,
556
- CustomerType: this.CustomerType,
557
- ItemId: this.ItemId,
558
- ItemType: this.ItemType,
559
- PriceId: this.PriceId,
560
- StartDateTime: this.StartDateTime,
561
- EndDateTime: this.EndDateTime,
562
- CancelRemarks: this.CancelRemarks,
563
- TerminateRemarks: this.TerminateRemarks,
564
- AgreementNo: this.AgreementNo,
565
- AccountType: this.AccountType,
566
- Status: this.Status,
567
- EscheatmentYN: this.EscheatmentYN,
568
- CreatedById: this.CreatedById,
569
- CreatedAt: this.CreatedAt,
570
- UpdatedById: this.UpdatedById,
571
- UpdatedAt: this.UpdatedAt,
572
- };
573
-
574
- // Record the Update Activity
575
- const activity = new Activity();
576
- activity.ActivityId = activity.createId();
577
- activity.Action = ActionEnum.UPDATE;
578
- activity.Description = 'Set Rental as Terminated';
579
- activity.EntityType = 'Rental';
580
- activity.EntityId = this.RentalId;
581
- activity.EntityValueBefore = JSON.stringify(entityValueBefore);
582
- activity.EntityValueAfter = JSON.stringify(entityValueAfter);
583
- await activity.create(loginUser.ObjectId, dbTransaction);
584
-
585
- return this;
586
- } catch (err) {
587
- throw err;
588
- }
589
- }
590
-
591
- async getCustomerActiveRentals(
592
- loginUser: LoginUser,
593
- dbTransaction: any,
594
- CustomerId: string,
595
- ): Promise<IRentalAttr[]> {
596
- try {
597
- // Part 1: Privilege Checking
598
- // Call loginUser.checkPrivileges() by passing:
599
- // SystemCode: <get_from_app_config>
600
- // PrivilegeCode: "RENTAL_VIEW"
601
- const systemCode =
602
- ApplicationConfig.getComponentConfigValue('system-code');
603
- const isPrivileged = loginUser.checkPrivileges(systemCode, 'RENTAL_VIEW');
604
-
605
- if (!isPrivileged) {
606
- throw new ClassError(
607
- 'Rental',
608
- 'RentalErrMsg01',
609
- "You do not have 'Rental - View' privilege.",
610
- );
611
- }
612
-
613
- // Part 2: Retrieve Rentals and Returns
614
- // Call Rental._Repo findAll method by passing:
615
- // where:
616
- // Status: "Active"
617
- // [Op.OR]:
618
- // CustomerId: Params.CustomerId
619
- // '$JointHirers.CustomerId$': Params.CustomerId
620
- // include:
621
- // model: JointHirerModel
622
- // attributes: []
623
- const query = `
624
- SELECT
625
- r.*
626
- FROM
627
- rental_Rental r
628
- LEFT JOIN
629
- rental_JointHirer jh ON r.RentalId = jh.RentalId
630
- WHERE
631
- r.Status = 'Active'
632
- AND (
633
- r.CustomerId = '${CustomerId}'
634
- OR jh.CustomerId = '${CustomerId}'
635
- )
636
- GROUP BY
637
- r.RentalId
638
- `;
639
- const db = rentalDb.getConnection();
640
- const result = await db.query(query, {
641
- type: QueryTypes.SELECT,
642
- transaction: dbTransaction,
643
- model: RentalModel,
644
- mapToModel: true,
645
- });
646
-
647
- // Format the returned records
648
- const records: IRentalAttr[] = result.map((record: RentalModel) => {
649
- return {
650
- RentalId: record.RentalId,
651
- CustomerId: record.CustomerId,
652
- CustomerType: record.CustomerType,
653
- ItemId: record.ItemId,
654
- ItemType: record.ItemType,
655
- PriceId: record.PriceId,
656
- StartDateTime: record.StartDateTime,
657
- EndDateTime: record.EndDateTime,
658
- CancelRemarks: record.CancelRemarks,
659
- TerminateRemarks: record.TerminateRemarks,
660
- AgreementNo: record.AgreementNo,
661
- AccountType: record.AccountType,
662
- Status: record.Status,
663
- EscheatmentYN: record.EscheatmentYN,
664
- CreatedById: record.CreatedById,
665
- CreatedAt: record.CreatedAt,
666
- UpdatedById: record.UpdatedById,
667
- UpdatedAt: record.UpdatedAt,
668
- };
669
- });
670
- // Return the returned records.
671
- return records;
672
- } catch (error) {
673
- throw error;
674
- }
675
- }
676
-
677
- async getCustomerIds(loginUser: LoginUser, dbTransaction: any) {
678
- try {
679
- // Part 1: Privilege Checking
680
- // Call loginUser.checkPrivileges() by passing:
681
- // SystemCode: <get_from_app_config>
682
- // PrivilegeCode: "RENTAL_VIEW"
683
- const systemCode =
684
- ApplicationConfig.getComponentConfigValue('system-code');
685
- const isPrivileged = loginUser.checkPrivileges(systemCode, 'RENTAL_VIEW');
686
-
687
- if (!isPrivileged) {
688
- throw new ClassError(
689
- 'Rental',
690
- 'RentalErrMsg01',
691
- "You do not have 'Rental - View' privilege.",
692
- );
693
- }
694
-
695
- // Part 2: Validation
696
- // Make sure this.RentalId exists, if not throw new ClassError by passing
697
- if (!this.RentalId) {
698
- throw new ClassError('Rental', 'RentalErrMsg01', 'RentalId is missing');
699
- }
700
-
701
- //Part 3: Retrieve Listing and Returns
702
- // 3.1 Call Rental._JointHirerRepo findAll method by passing:
703
- // where:
704
- // RentalId: this.RentalId
705
- // dbTransaction
706
- const options: any = {
707
- where: {
708
- RentalId: this.RentalId,
709
- },
710
- transaction: dbTransaction,
711
- };
712
-
713
- const joinHirers = await Rental._JointHirerRepo.findAll(options);
714
-
715
- // 3.2 Create a new array variable and set its value to joint hirer and Rental.CustomerId
716
- // array translated to only CustomerId. Then, append this.CustomerId to the array.
717
- const customerIds: string[] = [this.CustomerId];
718
- for (let i = 0; i < joinHirers.length; i++) {
719
- const jointHirer = joinHirers[i];
720
- customerIds.push(jointHirer.CustomerId);
721
- }
722
-
723
- // 3.3 Return the array.
724
- return customerIds;
725
- } catch (error) {
726
- throw error;
727
- }
728
- }
729
-
730
- async signAgreement(loginUser: LoginUser, dbTransaction: any) {
731
- try {
732
- // Part 1: Privilege Checking
733
- // Call loginUser.checkPrivileges() by passing:
734
- // SystemCode: <get_from_app_config>
735
- // PrivilegeCode: "RENTAL_SIGN"
736
- const systemCode =
737
- ApplicationConfig.getComponentConfigValue('system-code');
738
- const isPrivileged = loginUser.checkPrivileges(systemCode, 'RENTAL_SIGN');
739
-
740
- if (!isPrivileged) {
741
- throw new ClassError(
742
- 'Rental',
743
- 'RentalErrMsg01',
744
- "You do not have 'RENTAL_SIGN' privilege.",
745
- );
746
- }
747
-
748
- // Part 2: Validation
749
- // Make sure this.Status is "Pending Signing" and agreementStatus is "Generated", if not throw new ClassError
750
- const agreement = await Agreement.init(this.AgreementNo, dbTransaction);
751
- if (
752
- this.Status !== RentalStatusEnum.PENDING_SIGNING &&
753
- agreement.Status !== AggrementStatusEnum.GENERATED
754
- ) {
755
- throw new ClassError(
756
- 'Rental',
757
- 'RentalErrMsg01',
758
- 'Rental is not ready to be signed yet.',
759
- );
760
- }
761
-
762
- //Part 3: Update Agreement Status
763
- // 3.1 Set EntityValueBefore to current agreement instance.
764
- const entityValueAgreementBefore = {
765
- AgreementNo: agreement.AgreementNo,
766
- Status: agreement.Status,
767
- DateSigned: agreement.DateSigned,
768
- };
769
-
770
- // 3.2 Set below agreement attributes:
771
- // DateSigned: current date & time
772
- // Status: "Signed"
773
- const payload = {
774
- DateSigned: new Date(),
775
- Status: AggrementStatusEnum.SIGNED,
776
- };
777
-
778
- // 3.3 Call Rental._AgreementRepo update()
779
- await Rental._AgreementRepo.update(payload, {
780
- where: {
781
- AgreementNo: this.AgreementNo,
782
- },
783
- transaction: dbTransaction,
784
- });
785
-
786
- const entityValueAgreementAfter = {
787
- entityValueAgreementBefore,
788
- ...payload,
789
- };
790
-
791
- // Part 4: Record Update Agreement Activity
792
- const activity = new Activity();
793
- activity.ActivityId = activity.createId();
794
- activity.Action = ActionEnum.UPDATE;
795
- activity.Description = 'Update agreement';
796
- activity.EntityType = 'RentalAgreement';
797
- activity.EntityId = this.AgreementNo;
798
- activity.EntityValueBefore = JSON.stringify(entityValueAgreementBefore);
799
- activity.EntityValueAfter = JSON.stringify(entityValueAgreementAfter);
800
- await activity.create(loginUser.ObjectId, dbTransaction);
801
-
802
- // Part 5: Update Rental Status
803
- // 5.1 Set EntityValueBefore to current rental instance.
804
- const entityValueRentalBefore = {
805
- RentalId: this.RentalId,
806
- CustomerId: this.CustomerId,
807
- CustomerType: this.CustomerType,
808
- ItemId: this.ItemId,
809
- ItemType: this.ItemType,
810
- PriceId: this.PriceId,
811
- StartDateTime: this.StartDateTime,
812
- EndDateTime: this.EndDateTime,
813
- CancelRemarks: this.CancelRemarks,
814
- TerminateRemarks: this.TerminateRemarks,
815
- AgreementNo: this.AgreementNo,
816
- AccountType: this.AccountType,
817
- Status: this.Status,
818
- EscheatmentYN: this.EscheatmentYN,
819
- CreatedById: this.CreatedById,
820
- CreatedAt: this.CreatedAt,
821
- UpdatedById: this.UpdatedById,
822
- UpdatedAt: this.UpdatedAt,
823
- };
824
- // 5.2: Set below rental attributes:
825
- // Status: "Pending Key Collection"
826
- // UpdatedById: loginUser.ObjectId
827
- // UpdatedAt: current date & time
828
-
829
- const payloadRental = {
830
- Status: RentalStatusEnum.PENDING_KEY_COLLECTION,
831
- UpdatedById: loginUser.ObjectId,
832
- UpdatedAt: new Date(),
833
- };
834
-
835
- // 5.3: Call Rental._Repo update() method by passing:
836
- // populate rental instance attributes
837
- // dbTransaction
838
- await Rental._Repo.update(payloadRental, {
839
- where: {
840
- RentalId: this.RentalId,
841
- },
842
- transaction: dbTransaction,
843
- });
844
-
845
- const entityValueRentalAfter = {
846
- entityValueRentalBefore,
847
- ...payloadRental,
848
- };
849
-
850
- // Part 6: Record Update Agreement Activity
851
- const rentalActivity = new Activity();
852
- rentalActivity.ActivityId = activity.createId();
853
- rentalActivity.Action = ActionEnum.UPDATE;
854
- rentalActivity.Description = 'Sign rental agreement';
855
- rentalActivity.EntityType = 'Rental';
856
- rentalActivity.EntityId = this.RentalId;
857
- rentalActivity.EntityValueBefore = JSON.stringify(
858
- entityValueRentalBefore,
859
- );
860
- rentalActivity.EntityValueAfter = JSON.stringify(entityValueRentalAfter);
861
- await rentalActivity.create(loginUser.ObjectId, dbTransaction);
862
- } catch (error) {
863
- throw error;
864
- }
865
- }
866
-
867
- async generateAgreement(
868
- loginUser: LoginUser,
869
- dbTransaction: any,
870
- MediaId: string,
871
- ) {
872
- //This method will generate a new rental agreement.
873
- try {
874
- // Part 1: Privilege Checking
875
- // Call loginUser.checkPrivileges() by passing:
876
- // SystemCode: "<get_from_app_config>"
877
- // PrivilegeCode: "RENTAL_AGREEMENT_CREATE"
878
-
879
- const systemCode =
880
- ApplicationConfig.getComponentConfigValue('system-code');
881
- const isPrivileged = loginUser.checkPrivileges(
882
- systemCode,
883
- 'RENTAL_AGREEMENT_CREATE',
884
- );
885
-
886
- if (!isPrivileged) {
887
- throw new ClassError(
888
- 'Rental',
889
- 'RentalErrMsg01',
890
- "You do not have 'RENTAL_AGREEMENT_CREATE' privilege.",
891
- );
892
- }
893
-
894
- // Part 2: Validation
895
- // Instantiate existing RentalAgreement by passing:
896
- // dbTransaction
897
- // AgreementNo: this.AgreementNo
898
- // Make sure Params.MediaId exists, if not throw new ClassError by passing:
899
- // Classname: "Rental"
900
- // MessageCode: "RentalErrMsg0X"
901
- // Message: "MediaId is required."
902
- const agreement = await Agreement.init(this.AgreementNo, dbTransaction);
903
- if (!MediaId) {
904
- throw new ClassError(
905
- 'Rental',
906
- 'RentalErrMsg0X',
907
- 'MediaId is required.',
908
- );
909
- }
910
-
911
- // Part 3: Update Agreement Record
912
- // Set EntityValueBefore to the agreement instance.
913
- // Set below agreement attributes:
914
- // Status: "Generated"
915
- // MediaId: Params.MediaId
916
-
917
- const EntityValueBefore = agreement;
918
- agreement.Status = AggrementStatusEnum.GENERATED;
919
- agreement.MediaId = MediaId;
920
-
921
- // Call Rental._AgreementRepo update method by passing:
922
- // Status: agreement.Status
923
- // MediaId: agreement.MediaId
924
- // dbTransaction
925
-
926
- await Rental._AgreementRepo.update(
927
- {
928
- Status: agreement.Status,
929
- MediaId: agreement.MediaId,
930
- },
931
- {
932
- where: {
933
- AgreementNo: this.AgreementNo,
934
- },
935
- transaction: dbTransaction,
936
- },
937
- );
938
-
939
- // Part 4: Record Update Agreement Activity
940
- // Initialise EntityValueAfter variable and set to agreement instance
941
- const EntityValueAfter = agreement;
942
- // Instantiate new activity from Activity class, call createId() method, then set:
943
- const activity = new Activity();
944
- // Action: ActionEnum.UPDATE
945
- // Description: "Generate agreement."
946
- // EntityType: "RentalAgreement"
947
- // EntityId: this.AgreementNo
948
- // EntityValueBefore: EntityValueBefore
949
- // EntityValueAfter: EntityValueAfter
950
- activity.ActivityId = activity.createId();
951
- activity.Action = ActionEnum.UPDATE;
952
- activity.Description = 'Generate agreement.';
953
- activity.EntityType = 'RentalAgreement';
954
- activity.EntityId = this.AgreementNo;
955
- activity.EntityValueBefore = JSON.stringify(EntityValueBefore);
956
- activity.EntityValueAfter = JSON.stringify(EntityValueAfter);
957
-
958
- // Call new activity create method by passing:
959
- // dbTransaction
960
- // userId: loginUser.ObjectId
961
- await activity.create(loginUser.ObjectId, dbTransaction);
962
- } catch (error) {
963
- throw error;
964
- }
965
- }
966
- }
1
+ import { IRentalAttr } from '../../interfaces/rental-attr.interface';
2
+ import { RentalStatusEnum } from '../../enum/rental-status.enum';
3
+ import { RentalRepository } from './rental.repository';
4
+ import { ClassError, ObjectBase } from '@tomei/general';
5
+ import { ApplicationConfig } from '@tomei/config';
6
+ import { LoginUser } from '@tomei/sso';
7
+ import { RentalPrice } from '../rental-price/rental-price';
8
+ import { Op, QueryTypes } from 'sequelize';
9
+ import { ActionEnum, Activity } from '@tomei/activity-history';
10
+ import { IRentalFindAllSearchAttr } from '../../interfaces/rental-find-all-search-attr.interface';
11
+ import { RentalAccountTypeEnum } from '../../enum/account-type.enum';
12
+ import { JointHirer } from '../joint-hirer/joint-hirer';
13
+ import { JointHirerModel } from '../../models/joint-hirer.entity';
14
+ import { AgreementRepository } from '../agreement/agreement.repository';
15
+ import * as rentalDb from '../../database';
16
+ import { RentalModel } from '../../models/rental.entity';
17
+ import { JointHirerRepository } from '../joint-hirer/joint-hirer.repository';
18
+ import { AgreementModel } from '../../models';
19
+ import { Agreement } from '../agreement/agreement';
20
+ import { AggrementStatusEnum } from '../../enum/aggrement-status.enum';
21
+
22
+ export class Rental extends ObjectBase {
23
+ ObjectId: string;
24
+ ObjectName: string;
25
+ ObjectType = 'Rental';
26
+ TableName: string;
27
+ CustomerId: string;
28
+ CustomerType: string;
29
+ ItemId: string;
30
+ ItemType: string;
31
+ PriceId: string;
32
+ StartDateTime: Date;
33
+ EndDateTime: Date;
34
+ CancelRemarks: string;
35
+ TerminateRemarks: string;
36
+ AgreementNo: string;
37
+ AccountType: RentalAccountTypeEnum;
38
+ JointHirers: JointHirer[] = [];
39
+ protected _Status: RentalStatusEnum;
40
+ protected _EscheatmentYN: string = 'N';
41
+ protected _CreatedById: string;
42
+ protected _CreatedAt: Date;
43
+ protected _UpdatedById: string;
44
+ protected _UpdatedAt: Date;
45
+ protected static _Repo = new RentalRepository();
46
+ protected static _AgreementRepo = new AgreementRepository();
47
+ protected static _JointHirerRepo = new JointHirerRepository();
48
+
49
+ get RentalId(): string {
50
+ return this.ObjectId;
51
+ }
52
+
53
+ set RentalId(value: string) {
54
+ this.ObjectId = value;
55
+ }
56
+
57
+ get Status(): RentalStatusEnum {
58
+ return this._Status;
59
+ }
60
+
61
+ get EscheatmentYN(): string {
62
+ return this._EscheatmentYN;
63
+ }
64
+
65
+ get CreatedById(): string {
66
+ return this._CreatedById;
67
+ }
68
+
69
+ get CreatedAt(): Date {
70
+ return this._CreatedAt;
71
+ }
72
+
73
+ get UpdatedById(): string {
74
+ return this._UpdatedById;
75
+ }
76
+
77
+ get UpdatedAt(): Date {
78
+ return this._UpdatedAt;
79
+ }
80
+
81
+ private setTerminated() {
82
+ this._Status = RentalStatusEnum.TERMINATED;
83
+ }
84
+
85
+ protected constructor(rentalAttr?: IRentalAttr) {
86
+ super();
87
+ if (rentalAttr) {
88
+ this.RentalId = rentalAttr.RentalId;
89
+ this.CustomerId = rentalAttr.CustomerId;
90
+ this.CustomerType = rentalAttr.CustomerType;
91
+ this.ItemId = rentalAttr.ItemId;
92
+ this.ItemType = rentalAttr.ItemType;
93
+ this.PriceId = rentalAttr.PriceId;
94
+ this.StartDateTime = rentalAttr.StartDateTime;
95
+ this.EndDateTime = rentalAttr.EndDateTime;
96
+ this.CancelRemarks = rentalAttr.CancelRemarks;
97
+ this.TerminateRemarks = rentalAttr.TerminateRemarks;
98
+ this.AgreementNo = rentalAttr.AgreementNo;
99
+ this.AccountType = rentalAttr.AccountType;
100
+ this._Status = rentalAttr.Status;
101
+ this._EscheatmentYN = rentalAttr.EscheatmentYN;
102
+ this._CreatedById = rentalAttr.CreatedById;
103
+ this._CreatedAt = rentalAttr.CreatedAt;
104
+ this._UpdatedById = rentalAttr.UpdatedById;
105
+ this._UpdatedAt = rentalAttr.UpdatedAt;
106
+ }
107
+ }
108
+
109
+ public static async init(dbTransaction?: any, rentalId?: string) {
110
+ try {
111
+ if (rentalId) {
112
+ const rental = await Rental._Repo.findByPk(rentalId, dbTransaction);
113
+ if (rental) {
114
+ return new Rental(rental);
115
+ } else {
116
+ throw new ClassError('Rental', 'RentalErrMsg00', 'Rental Not Found');
117
+ }
118
+ }
119
+ return new Rental();
120
+ } catch (error) {
121
+ throw new ClassError(
122
+ 'Rental',
123
+ 'RentalErrMsg00',
124
+ 'Failed To Initialize Price',
125
+ );
126
+ }
127
+ }
128
+
129
+ /**
130
+ * Create a new Rental record.
131
+ * @param {RentalPrice} rentalPrice - The rental pricing information.
132
+ * @param {LoginUser} loginUser - The user initiating the creation.
133
+ * @param {any} [dbTransaction] - Optional database transaction for atomic operations.
134
+ * @throws {ClassError} Throws an error if:
135
+ * 1. loginUser does not have 'Rental - Create' privilege.
136
+ * 2. Rental item is not available at the current date.
137
+ * @returns {Promise<any>} A Promise resolving to the created rental record.
138
+ */
139
+ public async create(
140
+ rentalPrice: RentalPrice,
141
+ loginUser: LoginUser,
142
+ jointHirers?: JointHirer[],
143
+ dbTransaction?: any,
144
+ ): Promise<any> {
145
+ try {
146
+ /*Part 1: Check Privilege*/
147
+ const systemCode =
148
+ ApplicationConfig.getComponentConfigValue('system-code');
149
+ const isPrivileged = await loginUser.checkPrivileges(
150
+ systemCode,
151
+ 'Rental - Create',
152
+ );
153
+
154
+ if (!isPrivileged) {
155
+ throw new ClassError(
156
+ 'Rental',
157
+ 'RentalErrMsg01',
158
+ "You do not have 'Rental - Create' privilege.",
159
+ );
160
+ }
161
+
162
+ /*Part 2: Make Sure Rental Item Available*/
163
+ const isItemAvailable = await Rental.isItemAvailable(
164
+ this.ItemId,
165
+ this.ItemType,
166
+ this.StartDateTime,
167
+ this.EndDateTime,
168
+ dbTransaction,
169
+ );
170
+
171
+ if (!isItemAvailable) {
172
+ throw new ClassError(
173
+ 'Rental',
174
+ 'RentalErrMsg02',
175
+ 'Rental Item is not available at current date.',
176
+ );
177
+ }
178
+
179
+ // Part 3: Create Rental Agreement Record
180
+ // Call Rental._AgreementRepo create method by passing:
181
+ // AgreementNo: this.AgreementNo
182
+ // Status: "Not Generated"
183
+ // dbTransaction
184
+ await Rental._AgreementRepo.create(
185
+ {
186
+ AgreementNo: this.AgreementNo,
187
+ Status: 'Not Generated',
188
+ },
189
+ {
190
+ transaction: dbTransaction,
191
+ },
192
+ );
193
+
194
+ /*Part 4: Insert Rental & The Agreed Rental Price*/
195
+ if (!rentalPrice.PriceId) {
196
+ const rentalPriceData = await rentalPrice.create(
197
+ loginUser,
198
+ dbTransaction,
199
+ );
200
+ this.PriceId = rentalPriceData.PriceId;
201
+ } else {
202
+ this.PriceId = rentalPrice.PriceId;
203
+ }
204
+ this.RentalId = this.createId();
205
+ // if (!this.Status) {
206
+ this._Status = RentalStatusEnum.PENDING_SIGNING;
207
+ // }
208
+ this._CreatedById = loginUser.ObjectId;
209
+ this._UpdatedById = loginUser.ObjectId;
210
+ this._CreatedAt = new Date();
211
+ this._UpdatedAt = new Date();
212
+
213
+ const data = {
214
+ RentalId: this.RentalId,
215
+ CustomerId: this.CustomerId,
216
+ CustomerType: this.CustomerType,
217
+ ItemId: this.ItemId,
218
+ ItemType: this.ItemType,
219
+ PriceId: this.PriceId,
220
+ StartDateTime: this.StartDateTime,
221
+ EndDateTime: this.EndDateTime,
222
+ CancelRemarks: this.CancelRemarks,
223
+ TerminateRemarks: this.TerminateRemarks,
224
+ AgreementNo: this.AgreementNo,
225
+ AccountType: this.AccountType,
226
+ Status: this.Status,
227
+ EscheatmentYN: this.EscheatmentYN,
228
+ CreatedById: this.CreatedById,
229
+ CreatedAt: this.CreatedAt,
230
+ UpdatedById: this.UpdatedById,
231
+ UpdatedAt: this.UpdatedAt,
232
+ };
233
+
234
+ await Rental._Repo.create(data, {
235
+ transaction: dbTransaction,
236
+ });
237
+
238
+ //For every data inside Param.jointHirers, update the rentalId and call jointHirer.create
239
+ if (jointHirers) {
240
+ for (let i = 0; i < jointHirers.length; i++) {
241
+ jointHirers[i].RentalId = this.RentalId;
242
+ await jointHirers[i].create(loginUser, dbTransaction);
243
+ this.JointHirers.push(jointHirers[i]);
244
+ }
245
+ }
246
+
247
+ /*Part 5: Record Create Rental Activity*/
248
+ const activity = new Activity();
249
+ activity.ActivityId = activity.createId();
250
+ activity.Action = ActionEnum.CREATE;
251
+ activity.Description = 'Add Rental';
252
+ activity.EntityType = 'Rental';
253
+ activity.EntityId = this.RentalId;
254
+ activity.EntityValueBefore = JSON.stringify({});
255
+ activity.EntityValueAfter = JSON.stringify(data);
256
+ await activity.create(loginUser.ObjectId, dbTransaction);
257
+
258
+ /*Part 6: Return Result*/
259
+ return this;
260
+ } catch (error) {
261
+ throw error;
262
+ }
263
+ }
264
+
265
+ public static async isItemAvailable(
266
+ itemId: string,
267
+ itemType: string,
268
+ startDateTime: Date,
269
+ endDateTime: Date,
270
+ dbTransaction?: any,
271
+ ) {
272
+ try {
273
+ const item = await Rental._Repo.findOne({
274
+ where: {
275
+ ItemId: itemId,
276
+ ItemType: itemType,
277
+ StartDateTime: {
278
+ [Op.lte]: endDateTime,
279
+ },
280
+ EndDateTime: {
281
+ [Op.gte]: startDateTime,
282
+ },
283
+ },
284
+ transaction: dbTransaction,
285
+ });
286
+
287
+ if (item) {
288
+ return false;
289
+ } else {
290
+ return true;
291
+ }
292
+ } catch (error) {
293
+ throw error;
294
+ }
295
+ }
296
+
297
+ public static async findAll(
298
+ loginUser: LoginUser,
299
+ dbTransaction: any,
300
+ page?: number,
301
+ row?: number,
302
+ search?: IRentalFindAllSearchAttr,
303
+ ) {
304
+ try {
305
+ const systemCode =
306
+ await ApplicationConfig.getComponentConfigValue('system-code');
307
+
308
+ const isPrivileged = await loginUser.checkPrivileges(
309
+ systemCode,
310
+ 'Rental - View',
311
+ );
312
+
313
+ if (!isPrivileged) {
314
+ throw new ClassError(
315
+ 'Rental',
316
+ 'RentalErrMsg01',
317
+ "You do not have 'Rental - View' privilege.",
318
+ );
319
+ }
320
+
321
+ const queryObj: any = {};
322
+
323
+ let options: any = {
324
+ transaction: dbTransaction,
325
+ order: [['CreatedAt', 'DESC']],
326
+ };
327
+
328
+ if (page && row) {
329
+ options = {
330
+ ...options,
331
+ limit: row,
332
+ offset: row * (page - 1),
333
+ };
334
+ }
335
+
336
+ if (search) {
337
+ Object.entries(search).forEach(([key, value]) => {
338
+ if (key === 'StartDateTime') {
339
+ queryObj[key] = {
340
+ [Op.gte]: value,
341
+ };
342
+ } else if (key === 'EndDateTime') {
343
+ queryObj[key] = {
344
+ [Op.lte]: value,
345
+ };
346
+ } else if (key === 'CustomerId') {
347
+ queryObj[key] = {
348
+ [Op.substring]: value,
349
+ };
350
+
351
+ options.include = [
352
+ {
353
+ model: JointHirerModel,
354
+ required: false,
355
+ where: {
356
+ CustomerId: {
357
+ [Op.substring]: value,
358
+ },
359
+ },
360
+ },
361
+ ];
362
+ } else {
363
+ queryObj[key] = {
364
+ [Op.substring]: value,
365
+ };
366
+ }
367
+ });
368
+ if (options?.include?.length > 1) {
369
+ options.include.push({
370
+ model: AgreementModel,
371
+ required: false,
372
+ });
373
+ } else {
374
+ options.include = [
375
+ {
376
+ model: AgreementModel,
377
+ required: false,
378
+ },
379
+ ];
380
+ }
381
+
382
+ options = {
383
+ ...options,
384
+ where: queryObj,
385
+ };
386
+ }
387
+
388
+ return await Rental._Repo.findAndCountAll(options);
389
+ } catch (err) {
390
+ throw err;
391
+ }
392
+ }
393
+
394
+ public static async checkActiveByItemId(
395
+ loginUser: LoginUser,
396
+ itemId: string,
397
+ itemType: string,
398
+ dbTransaction?: any,
399
+ ) {
400
+ try {
401
+ const systemCode =
402
+ await ApplicationConfig.getComponentConfigValue('system-code');
403
+
404
+ const isPrivileged = await loginUser.checkPrivileges(
405
+ systemCode,
406
+ 'Rental - View',
407
+ );
408
+
409
+ if (!isPrivileged) {
410
+ throw new ClassError(
411
+ 'Rental',
412
+ 'RentalErrMsg01',
413
+ "You do not have 'Rental - View' privilege.",
414
+ );
415
+ }
416
+
417
+ const queryObj: any = {
418
+ ItemId: itemId,
419
+ ItemType: itemType,
420
+ Status: RentalStatusEnum.ACTIVE,
421
+ };
422
+
423
+ const options: any = {
424
+ transaction: dbTransaction,
425
+ where: queryObj,
426
+ };
427
+
428
+ const rental = await Rental._Repo.findOne(options);
429
+
430
+ if (rental) {
431
+ return true;
432
+ } else {
433
+ return false;
434
+ }
435
+ } catch (err) {
436
+ throw err;
437
+ }
438
+ }
439
+
440
+ /**
441
+ * Sets the StartDateTime property of the Rental class as custom setter.
442
+ * @param {Date} startDateTime - The start date and time of the rental.
443
+ * @throws {ClassError} Throws an error if:
444
+ * 1. startDateTime is a past date.
445
+ * 2. startDateTime is more than the EndDateTime.
446
+ * @returns {void}
447
+ */
448
+ setStartDateTime(startDateTime: Date): void {
449
+ const startDateTimeObject = new Date(startDateTime);
450
+ startDateTimeObject.setHours(0, 0, 0, 0);
451
+
452
+ /*Part 1: Make Sure Future Date Time*/
453
+ if (startDateTimeObject < new Date(new Date().setHours(0, 0, 0, 0))) {
454
+ throw new ClassError(
455
+ 'Rental',
456
+ 'RentalErrMsg02',
457
+ 'StartDateTime cannot be a past datetime.',
458
+ );
459
+ }
460
+
461
+ /*Part 2: Make Sure Less Than End Date Time*/
462
+ if (this.EndDateTime && startDateTimeObject > this.EndDateTime) {
463
+ throw new ClassError(
464
+ 'Rental',
465
+ 'RentalErrMsg03',
466
+ 'StartDateTime cannot be more than EndDateTime.',
467
+ );
468
+ }
469
+
470
+ /*Part 3: Set Status Whether Reserved or Active*/
471
+ if (startDateTimeObject > new Date(new Date().setHours(0, 0, 0, 0))) {
472
+ this._Status = RentalStatusEnum.RESERVED;
473
+ } else {
474
+ this._Status = RentalStatusEnum.ACTIVE;
475
+ }
476
+ }
477
+
478
+ public async periodEndProcess(
479
+ loginUser: LoginUser,
480
+ dbTransaction: any,
481
+ stockInventory: any,
482
+ ) {
483
+ try {
484
+ // Privilege Checking
485
+ const systemCode =
486
+ await ApplicationConfig.getComponentConfigValue('system-code');
487
+
488
+ const isPrivileged = await loginUser.checkPrivileges(
489
+ systemCode,
490
+ 'Rental – PeriodEndProcess',
491
+ );
492
+
493
+ if (!isPrivileged) {
494
+ throw new ClassError(
495
+ 'Rental',
496
+ 'RentalErrMsg04',
497
+ "You do not have 'Rental - PeriodEndProcess' privilege.",
498
+ );
499
+ }
500
+
501
+ // Validate Existing Rental
502
+ if (this.AgreementNo === undefined || this.AgreementNo === null) {
503
+ throw new ClassError(
504
+ 'Rental',
505
+ 'RentalErrMsg05',
506
+ 'Rental must be existing rental.',
507
+ );
508
+ }
509
+
510
+ // Validate Rental End Period
511
+ if (this.EndDateTime === new Date(new Date().setHours(0, 0, 0, 0))) {
512
+ throw new ClassError(
513
+ 'Rental',
514
+ 'RentalErrMsg06',
515
+ 'Rental period is not ending today.',
516
+ );
517
+ }
518
+
519
+ // Mark Rental Item as Available
520
+ await stockInventory.setAvailable(loginUser, dbTransaction);
521
+
522
+ // Capture Record Info Before Changes
523
+ const entityValueBefore = {
524
+ RentalId: this.RentalId,
525
+ CustomerId: this.CustomerId,
526
+ CustomerType: this.CustomerType,
527
+ ItemId: this.ItemId,
528
+ ItemType: this.ItemType,
529
+ PriceId: this.PriceId,
530
+ StartDateTime: this.StartDateTime,
531
+ EndDateTime: this.EndDateTime,
532
+ CancelRemarks: this.CancelRemarks,
533
+ TerminateRemarks: this.TerminateRemarks,
534
+ AgreementNo: this.AgreementNo,
535
+ AccountType: this.AccountType,
536
+ Status: this.Status,
537
+ EscheatmentYN: this.EscheatmentYN,
538
+ CreatedById: this.CreatedById,
539
+ CreatedAt: this.CreatedAt,
540
+ UpdatedById: this.UpdatedById,
541
+ UpdatedAt: this.UpdatedAt,
542
+ };
543
+
544
+ // Mark Rental as Terminated and Capture Updater Info
545
+ this.setTerminated();
546
+ this._UpdatedById = loginUser.ObjectId;
547
+ this._UpdatedAt = new Date();
548
+
549
+ // Capture Record Info after Changes
550
+ const entityValueAfter = {
551
+ RentalId: this.RentalId,
552
+ CustomerId: this.CustomerId,
553
+ CustomerType: this.CustomerType,
554
+ ItemId: this.ItemId,
555
+ ItemType: this.ItemType,
556
+ PriceId: this.PriceId,
557
+ StartDateTime: this.StartDateTime,
558
+ EndDateTime: this.EndDateTime,
559
+ CancelRemarks: this.CancelRemarks,
560
+ TerminateRemarks: this.TerminateRemarks,
561
+ AgreementNo: this.AgreementNo,
562
+ AccountType: this.AccountType,
563
+ Status: this.Status,
564
+ EscheatmentYN: this.EscheatmentYN,
565
+ CreatedById: this.CreatedById,
566
+ CreatedAt: this.CreatedAt,
567
+ UpdatedById: this.UpdatedById,
568
+ UpdatedAt: this.UpdatedAt,
569
+ };
570
+
571
+ // Record the Update Activity
572
+ const activity = new Activity();
573
+ activity.ActivityId = activity.createId();
574
+ activity.Action = ActionEnum.UPDATE;
575
+ activity.Description = 'Set Rental as Terminated';
576
+ activity.EntityType = 'Rental';
577
+ activity.EntityId = this.RentalId;
578
+ activity.EntityValueBefore = JSON.stringify(entityValueBefore);
579
+ activity.EntityValueAfter = JSON.stringify(entityValueAfter);
580
+ await activity.create(loginUser.ObjectId, dbTransaction);
581
+
582
+ return this;
583
+ } catch (err) {
584
+ throw err;
585
+ }
586
+ }
587
+
588
+ async getCustomerActiveRentals(
589
+ loginUser: LoginUser,
590
+ dbTransaction: any,
591
+ CustomerId: string,
592
+ ): Promise<IRentalAttr[]> {
593
+ try {
594
+ // Part 1: Privilege Checking
595
+ // Call loginUser.checkPrivileges() by passing:
596
+ // SystemCode: <get_from_app_config>
597
+ // PrivilegeCode: "RENTAL_VIEW"
598
+ const systemCode =
599
+ ApplicationConfig.getComponentConfigValue('system-code');
600
+ const isPrivileged = loginUser.checkPrivileges(systemCode, 'RENTAL_VIEW');
601
+
602
+ if (!isPrivileged) {
603
+ throw new ClassError(
604
+ 'Rental',
605
+ 'RentalErrMsg01',
606
+ "You do not have 'Rental - View' privilege.",
607
+ );
608
+ }
609
+
610
+ // Part 2: Retrieve Rentals and Returns
611
+ // Call Rental._Repo findAll method by passing:
612
+ // where:
613
+ // Status: "Active"
614
+ // [Op.OR]:
615
+ // CustomerId: Params.CustomerId
616
+ // '$JointHirers.CustomerId$': Params.CustomerId
617
+ // include:
618
+ // model: JointHirerModel
619
+ // attributes: []
620
+ const query = `
621
+ SELECT
622
+ r.*
623
+ FROM
624
+ rental_Rental r
625
+ LEFT JOIN
626
+ rental_JointHirer jh ON r.RentalId = jh.RentalId
627
+ WHERE
628
+ r.Status = 'Active'
629
+ AND (
630
+ r.CustomerId = '${CustomerId}'
631
+ OR jh.CustomerId = '${CustomerId}'
632
+ )
633
+ GROUP BY
634
+ r.RentalId
635
+ `;
636
+ const db = rentalDb.getConnection();
637
+ const result = await db.query(query, {
638
+ type: QueryTypes.SELECT,
639
+ transaction: dbTransaction,
640
+ model: RentalModel,
641
+ mapToModel: true,
642
+ });
643
+
644
+ // Format the returned records
645
+ const records: IRentalAttr[] = result.map((record: RentalModel) => {
646
+ return {
647
+ RentalId: record.RentalId,
648
+ CustomerId: record.CustomerId,
649
+ CustomerType: record.CustomerType,
650
+ ItemId: record.ItemId,
651
+ ItemType: record.ItemType,
652
+ PriceId: record.PriceId,
653
+ StartDateTime: record.StartDateTime,
654
+ EndDateTime: record.EndDateTime,
655
+ CancelRemarks: record.CancelRemarks,
656
+ TerminateRemarks: record.TerminateRemarks,
657
+ AgreementNo: record.AgreementNo,
658
+ AccountType: record.AccountType,
659
+ Status: record.Status,
660
+ EscheatmentYN: record.EscheatmentYN,
661
+ CreatedById: record.CreatedById,
662
+ CreatedAt: record.CreatedAt,
663
+ UpdatedById: record.UpdatedById,
664
+ UpdatedAt: record.UpdatedAt,
665
+ };
666
+ });
667
+ // Return the returned records.
668
+ return records;
669
+ } catch (error) {
670
+ throw error;
671
+ }
672
+ }
673
+
674
+ async getCustomerIds(loginUser: LoginUser, dbTransaction: any) {
675
+ try {
676
+ // Part 1: Privilege Checking
677
+ // Call loginUser.checkPrivileges() by passing:
678
+ // SystemCode: <get_from_app_config>
679
+ // PrivilegeCode: "RENTAL_VIEW"
680
+ const systemCode =
681
+ ApplicationConfig.getComponentConfigValue('system-code');
682
+ const isPrivileged = loginUser.checkPrivileges(systemCode, 'RENTAL_VIEW');
683
+
684
+ if (!isPrivileged) {
685
+ throw new ClassError(
686
+ 'Rental',
687
+ 'RentalErrMsg01',
688
+ "You do not have 'Rental - View' privilege.",
689
+ );
690
+ }
691
+
692
+ // Part 2: Validation
693
+ // Make sure this.RentalId exists, if not throw new ClassError by passing
694
+ if (!this.RentalId) {
695
+ throw new ClassError('Rental', 'RentalErrMsg01', 'RentalId is missing');
696
+ }
697
+
698
+ //Part 3: Retrieve Listing and Returns
699
+ // 3.1 Call Rental._JointHirerRepo findAll method by passing:
700
+ // where:
701
+ // RentalId: this.RentalId
702
+ // dbTransaction
703
+ const options: any = {
704
+ where: {
705
+ RentalId: this.RentalId,
706
+ },
707
+ transaction: dbTransaction,
708
+ };
709
+
710
+ const joinHirers = await Rental._JointHirerRepo.findAll(options);
711
+
712
+ // 3.2 Create a new array variable and set its value to joint hirer and Rental.CustomerId
713
+ // array translated to only CustomerId. Then, append this.CustomerId to the array.
714
+ const customerIds: string[] = [this.CustomerId];
715
+ for (let i = 0; i < joinHirers.length; i++) {
716
+ const jointHirer = joinHirers[i];
717
+ customerIds.push(jointHirer.CustomerId);
718
+ }
719
+
720
+ // 3.3 Return the array.
721
+ return customerIds;
722
+ } catch (error) {
723
+ throw error;
724
+ }
725
+ }
726
+
727
+ async signAgreement(loginUser: LoginUser, dbTransaction: any) {
728
+ try {
729
+ // Part 1: Privilege Checking
730
+ // Call loginUser.checkPrivileges() by passing:
731
+ // SystemCode: <get_from_app_config>
732
+ // PrivilegeCode: "RENTAL_SIGN"
733
+ const systemCode =
734
+ ApplicationConfig.getComponentConfigValue('system-code');
735
+ const isPrivileged = loginUser.checkPrivileges(systemCode, 'RENTAL_SIGN');
736
+
737
+ if (!isPrivileged) {
738
+ throw new ClassError(
739
+ 'Rental',
740
+ 'RentalErrMsg01',
741
+ "You do not have 'RENTAL_SIGN' privilege.",
742
+ );
743
+ }
744
+
745
+ // Part 2: Validation
746
+ // Make sure this.Status is "Pending Signing" and agreementStatus is "Generated", if not throw new ClassError
747
+ const agreement = await Agreement.init(this.AgreementNo, dbTransaction);
748
+ if (
749
+ this.Status !== RentalStatusEnum.PENDING_SIGNING &&
750
+ agreement.Status !== AggrementStatusEnum.GENERATED
751
+ ) {
752
+ throw new ClassError(
753
+ 'Rental',
754
+ 'RentalErrMsg01',
755
+ 'Rental is not ready to be signed yet.',
756
+ );
757
+ }
758
+
759
+ //Part 3: Update Agreement Status
760
+ // 3.1 Set EntityValueBefore to current agreement instance.
761
+ const entityValueAgreementBefore = {
762
+ AgreementNo: agreement.AgreementNo,
763
+ Status: agreement.Status,
764
+ DateSigned: agreement.DateSigned,
765
+ };
766
+
767
+ // 3.2 Set below agreement attributes:
768
+ // DateSigned: current date & time
769
+ // Status: "Signed"
770
+ const payload = {
771
+ DateSigned: new Date(),
772
+ Status: AggrementStatusEnum.SIGNED,
773
+ };
774
+
775
+ // 3.3 Call Rental._AgreementRepo update()
776
+ await Rental._AgreementRepo.update(payload, {
777
+ where: {
778
+ AgreementNo: this.AgreementNo,
779
+ },
780
+ transaction: dbTransaction,
781
+ });
782
+
783
+ const entityValueAgreementAfter = {
784
+ entityValueAgreementBefore,
785
+ ...payload,
786
+ };
787
+
788
+ // Part 4: Record Update Agreement Activity
789
+ const activity = new Activity();
790
+ activity.ActivityId = activity.createId();
791
+ activity.Action = ActionEnum.UPDATE;
792
+ activity.Description = 'Update agreement';
793
+ activity.EntityType = 'RentalAgreement';
794
+ activity.EntityId = this.AgreementNo;
795
+ activity.EntityValueBefore = JSON.stringify(entityValueAgreementBefore);
796
+ activity.EntityValueAfter = JSON.stringify(entityValueAgreementAfter);
797
+ await activity.create(loginUser.ObjectId, dbTransaction);
798
+
799
+ // Part 5: Update Rental Status
800
+ // 5.1 Set EntityValueBefore to current rental instance.
801
+ const entityValueRentalBefore = {
802
+ RentalId: this.RentalId,
803
+ CustomerId: this.CustomerId,
804
+ CustomerType: this.CustomerType,
805
+ ItemId: this.ItemId,
806
+ ItemType: this.ItemType,
807
+ PriceId: this.PriceId,
808
+ StartDateTime: this.StartDateTime,
809
+ EndDateTime: this.EndDateTime,
810
+ CancelRemarks: this.CancelRemarks,
811
+ TerminateRemarks: this.TerminateRemarks,
812
+ AgreementNo: this.AgreementNo,
813
+ AccountType: this.AccountType,
814
+ Status: this.Status,
815
+ EscheatmentYN: this.EscheatmentYN,
816
+ CreatedById: this.CreatedById,
817
+ CreatedAt: this.CreatedAt,
818
+ UpdatedById: this.UpdatedById,
819
+ UpdatedAt: this.UpdatedAt,
820
+ };
821
+ // 5.2: Set below rental attributes:
822
+ // Status: "Pending Key Collection"
823
+ // UpdatedById: loginUser.ObjectId
824
+ // UpdatedAt: current date & time
825
+
826
+ const payloadRental = {
827
+ Status: RentalStatusEnum.PENDING_KEY_COLLECTION,
828
+ UpdatedById: loginUser.ObjectId,
829
+ UpdatedAt: new Date(),
830
+ };
831
+
832
+ // 5.3: Call Rental._Repo update() method by passing:
833
+ // populate rental instance attributes
834
+ // dbTransaction
835
+ await Rental._Repo.update(payloadRental, {
836
+ where: {
837
+ RentalId: this.RentalId,
838
+ },
839
+ transaction: dbTransaction,
840
+ });
841
+
842
+ const entityValueRentalAfter = {
843
+ entityValueRentalBefore,
844
+ ...payloadRental,
845
+ };
846
+
847
+ // Part 6: Record Update Agreement Activity
848
+ const rentalActivity = new Activity();
849
+ rentalActivity.ActivityId = activity.createId();
850
+ rentalActivity.Action = ActionEnum.UPDATE;
851
+ rentalActivity.Description = 'Sign rental agreement';
852
+ rentalActivity.EntityType = 'Rental';
853
+ rentalActivity.EntityId = this.RentalId;
854
+ rentalActivity.EntityValueBefore = JSON.stringify(
855
+ entityValueRentalBefore,
856
+ );
857
+ rentalActivity.EntityValueAfter = JSON.stringify(entityValueRentalAfter);
858
+ await rentalActivity.create(loginUser.ObjectId, dbTransaction);
859
+ } catch (error) {
860
+ throw error;
861
+ }
862
+ }
863
+
864
+ async generateAgreement(
865
+ loginUser: LoginUser,
866
+ dbTransaction: any,
867
+ MediaId: string,
868
+ ) {
869
+ //This method will generate a new rental agreement.
870
+ try {
871
+ // Part 1: Privilege Checking
872
+ // Call loginUser.checkPrivileges() by passing:
873
+ // SystemCode: "<get_from_app_config>"
874
+ // PrivilegeCode: "RENTAL_AGREEMENT_CREATE"
875
+
876
+ const systemCode =
877
+ ApplicationConfig.getComponentConfigValue('system-code');
878
+ const isPrivileged = loginUser.checkPrivileges(
879
+ systemCode,
880
+ 'RENTAL_AGREEMENT_CREATE',
881
+ );
882
+
883
+ if (!isPrivileged) {
884
+ throw new ClassError(
885
+ 'Rental',
886
+ 'RentalErrMsg01',
887
+ "You do not have 'RENTAL_AGREEMENT_CREATE' privilege.",
888
+ );
889
+ }
890
+
891
+ // Part 2: Validation
892
+ // Instantiate existing RentalAgreement by passing:
893
+ // dbTransaction
894
+ // AgreementNo: this.AgreementNo
895
+ // Make sure Params.MediaId exists, if not throw new ClassError by passing:
896
+ // Classname: "Rental"
897
+ // MessageCode: "RentalErrMsg0X"
898
+ // Message: "MediaId is required."
899
+ const agreement = await Agreement.init(this.AgreementNo, dbTransaction);
900
+ if (!MediaId) {
901
+ throw new ClassError(
902
+ 'Rental',
903
+ 'RentalErrMsg0X',
904
+ 'MediaId is required.',
905
+ );
906
+ }
907
+
908
+ // Part 3: Update Agreement Record
909
+ // Set EntityValueBefore to the agreement instance.
910
+ // Set below agreement attributes:
911
+ // Status: "Generated"
912
+ // MediaId: Params.MediaId
913
+
914
+ const EntityValueBefore = agreement;
915
+ agreement.Status = AggrementStatusEnum.GENERATED;
916
+ agreement.MediaId = MediaId;
917
+
918
+ // Call Rental._AgreementRepo update method by passing:
919
+ // Status: agreement.Status
920
+ // MediaId: agreement.MediaId
921
+ // dbTransaction
922
+
923
+ await Rental._AgreementRepo.update(
924
+ {
925
+ Status: agreement.Status,
926
+ MediaId: agreement.MediaId,
927
+ },
928
+ {
929
+ where: {
930
+ AgreementNo: this.AgreementNo,
931
+ },
932
+ transaction: dbTransaction,
933
+ },
934
+ );
935
+
936
+ // Part 4: Record Update Agreement Activity
937
+ // Initialise EntityValueAfter variable and set to agreement instance
938
+ const EntityValueAfter = agreement;
939
+ // Instantiate new activity from Activity class, call createId() method, then set:
940
+ const activity = new Activity();
941
+ // Action: ActionEnum.UPDATE
942
+ // Description: "Generate agreement."
943
+ // EntityType: "RentalAgreement"
944
+ // EntityId: this.AgreementNo
945
+ // EntityValueBefore: EntityValueBefore
946
+ // EntityValueAfter: EntityValueAfter
947
+ activity.ActivityId = activity.createId();
948
+ activity.Action = ActionEnum.UPDATE;
949
+ activity.Description = 'Generate agreement.';
950
+ activity.EntityType = 'RentalAgreement';
951
+ activity.EntityId = this.AgreementNo;
952
+ activity.EntityValueBefore = JSON.stringify(EntityValueBefore);
953
+ activity.EntityValueAfter = JSON.stringify(EntityValueAfter);
954
+
955
+ // Call new activity create method by passing:
956
+ // dbTransaction
957
+ // userId: loginUser.ObjectId
958
+ await activity.create(loginUser.ObjectId, dbTransaction);
959
+ } catch (error) {
960
+ throw error;
961
+ }
962
+ }
963
+ }