@tomei/rental 0.11.0 → 0.11.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.
- package/.commitlintrc.json +22 -22
- package/.eslintrc +16 -16
- package/.eslintrc.js +35 -35
- package/.gitlab-ci.yml +16 -16
- package/.husky/commit-msg +15 -15
- package/.husky/pre-commit +7 -7
- package/.prettierrc +4 -4
- package/Jenkinsfile +51 -51
- package/README.md +8 -8
- package/dist/src/components/rental/rental.js +23 -17
- package/dist/src/components/rental/rental.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/jest.config.js +10 -10
- package/migrations/booking-table-migration.js +79 -79
- package/migrations/joint-hirer-table-migration.js +52 -52
- package/migrations/rental-aggrement-table-migration.js +30 -30
- package/migrations/rental-price-table-migration.js +32 -32
- package/migrations/rental-table-migrations.js +96 -96
- package/package.json +75 -75
- package/sonar-project.properties +12 -12
- package/src/components/agreement/agreement.repository.ts +54 -54
- package/src/components/agreement/agreement.ts +49 -49
- package/src/components/booking/booking.repository.ts +51 -51
- package/src/components/booking/booking.ts +343 -343
- package/src/components/joint-hirer/joint-hirer.repository.ts +54 -54
- package/src/components/rental/rental.repository.ts +51 -51
- package/src/components/rental/rental.ts +966 -960
- package/src/components/rental-price/rental-price.repository.ts +54 -54
- package/src/components/rental-price/rental-price.ts +100 -100
- package/src/database.ts +27 -27
- package/src/enum/account-type.enum.ts +4 -4
- package/src/enum/booking.enum.ts +5 -5
- package/src/enum/index.ts +11 -11
- package/src/enum/rental-status.enum.ts +39 -39
- package/src/index.ts +28 -28
- package/src/interfaces/agreement-attr.interface.ts +7 -7
- package/src/interfaces/booking-attr.interface.ts +19 -19
- package/src/interfaces/booking-find-all-search-attr.interface.ts +12 -12
- package/src/interfaces/index.ts +15 -15
- package/src/interfaces/joint-hirer-attr.interface.ts +10 -10
- package/src/interfaces/rental-attr.interface.ts +25 -25
- package/src/interfaces/rental-find-all-search-attr.interface.ts +11 -11
- package/src/interfaces/rental-price-attr.interface.ts +7 -7
- package/src/models/agreement.entity.ts +39 -39
- package/src/models/booking.entity.ts +105 -105
- package/src/models/index.ts +13 -13
- package/src/models/joint-hirer.entity.ts +63 -63
- package/src/models/rental-price.entity.ts +38 -38
- package/src/models/rental.entity.ts +133 -133
- package/tsconfig.build.json +5 -5
- package/tsconfig.json +23 -23
|
@@ -1,343 +1,343 @@
|
|
|
1
|
-
import { ClassError, ObjectBase } from '@tomei/general';
|
|
2
|
-
import { BookingStatusEnum } from '../../enum/booking.enum';
|
|
3
|
-
import { IBookingAttr } from '../../interfaces/booking-attr.interface';
|
|
4
|
-
import { BookingRepository } from './booking.repository';
|
|
5
|
-
import { DateTime } from 'luxon';
|
|
6
|
-
import { LoginUser } from '@tomei/sso';
|
|
7
|
-
import { RentalPrice } from '../rental-price/rental-price';
|
|
8
|
-
import { ApplicationConfig } from '@tomei/config';
|
|
9
|
-
import { Op } from 'sequelize';
|
|
10
|
-
import { Rental } from '../rental/rental';
|
|
11
|
-
import { ActionEnum, Activity } from '@tomei/activity-history';
|
|
12
|
-
import { IBookingFindAllSearchAttr } from '../../interfaces/booking-find-all-search-attr.interface';
|
|
13
|
-
|
|
14
|
-
export class Booking extends ObjectBase {
|
|
15
|
-
ObjectId: string;
|
|
16
|
-
ObjectName: string;
|
|
17
|
-
ObjectType: string = 'Booking';
|
|
18
|
-
TableName = 'booking_Booking';
|
|
19
|
-
CustomerId: string;
|
|
20
|
-
CustomerType: string;
|
|
21
|
-
ItemId: string;
|
|
22
|
-
ItemType: string;
|
|
23
|
-
PriceId: string;
|
|
24
|
-
protected _ScheduledStartDateTime: Date;
|
|
25
|
-
protected _ScheduledEndDateTime: Date;
|
|
26
|
-
BookingFee: number;
|
|
27
|
-
Status: BookingStatusEnum;
|
|
28
|
-
CancelRemarks: string;
|
|
29
|
-
protected _CreatedById: string;
|
|
30
|
-
protected _CreatedAt: Date;
|
|
31
|
-
protected _UpdatedById: string;
|
|
32
|
-
protected _UpdatedAt: Date;
|
|
33
|
-
|
|
34
|
-
protected static _Repo = new BookingRepository();
|
|
35
|
-
|
|
36
|
-
get BookingNo(): string {
|
|
37
|
-
return this.ObjectId;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
set BookingNo(value: string) {
|
|
41
|
-
this.ObjectId = value;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
get CreatedById(): string {
|
|
45
|
-
return this._CreatedById;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
get CreatedAt(): Date {
|
|
49
|
-
return this._CreatedAt;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
get UpdatedById(): string {
|
|
53
|
-
return this._UpdatedById;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
get UpdatedAt(): Date {
|
|
57
|
-
return this._UpdatedAt;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
get ScheduledStartDateTime(): Date {
|
|
61
|
-
return this._ScheduledStartDateTime;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
get ScheduledEndDateTime(): Date {
|
|
65
|
-
return this._ScheduledEndDateTime;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
async setScheduledStartDateTime(datetime: Date) {
|
|
69
|
-
const dateTime = DateTime.fromJSDate(datetime);
|
|
70
|
-
const currentDateTime = DateTime.now();
|
|
71
|
-
if (dateTime <= currentDateTime) {
|
|
72
|
-
throw new ClassError(
|
|
73
|
-
'Booking',
|
|
74
|
-
'BookingErrMsg01',
|
|
75
|
-
'Booking must be for future date time.',
|
|
76
|
-
);
|
|
77
|
-
}
|
|
78
|
-
this._ScheduledStartDateTime = datetime;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
async setScheduledEndDateTime(datetime: Date) {
|
|
82
|
-
const dateTime = DateTime.fromJSDate(datetime);
|
|
83
|
-
const currentDateTime = DateTime.now();
|
|
84
|
-
if (dateTime <= currentDateTime) {
|
|
85
|
-
throw new ClassError(
|
|
86
|
-
'Booking',
|
|
87
|
-
'BookingErrMsg01',
|
|
88
|
-
'Booking must be for future date time.',
|
|
89
|
-
);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
if (!this._ScheduledStartDateTime) {
|
|
93
|
-
throw new ClassError(
|
|
94
|
-
'Booking',
|
|
95
|
-
'BookingErrMsg01',
|
|
96
|
-
'Booking start date time must be set before setting end date time.',
|
|
97
|
-
);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
const startDateTime = DateTime.fromJSDate(this._ScheduledStartDateTime);
|
|
101
|
-
if (dateTime <= startDateTime) {
|
|
102
|
-
throw new ClassError(
|
|
103
|
-
'Booking',
|
|
104
|
-
'BookingErrMsg03',
|
|
105
|
-
'Booking end date time must be more than start date time.',
|
|
106
|
-
);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
this._ScheduledEndDateTime = datetime;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
protected constructor(bookingAttr?: IBookingAttr) {
|
|
113
|
-
super();
|
|
114
|
-
if (bookingAttr) {
|
|
115
|
-
this.ObjectId = bookingAttr.BookingNo;
|
|
116
|
-
this.CustomerId = bookingAttr.CustomerId;
|
|
117
|
-
this.CustomerType = bookingAttr.CustomerType;
|
|
118
|
-
this.ItemId = bookingAttr.ItemId;
|
|
119
|
-
this.ItemType = bookingAttr.ItemType;
|
|
120
|
-
this.PriceId = bookingAttr.PriceId;
|
|
121
|
-
this._ScheduledStartDateTime = bookingAttr.ScheduledStartDateTime;
|
|
122
|
-
this._ScheduledEndDateTime = bookingAttr.ScheduledEndDateTime;
|
|
123
|
-
this.BookingFee = bookingAttr.BookingFee;
|
|
124
|
-
this.Status = bookingAttr.Status;
|
|
125
|
-
this.CancelRemarks = bookingAttr.CancelRemarks;
|
|
126
|
-
this._CreatedById = bookingAttr.CreatedById;
|
|
127
|
-
this._CreatedAt = bookingAttr.CreatedAt;
|
|
128
|
-
this._UpdatedById = bookingAttr.UpdatedById;
|
|
129
|
-
this._UpdatedAt = bookingAttr.UpdatedAt;
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
public static async init(dbTransaction?: any, bookingNo?: string) {
|
|
134
|
-
try {
|
|
135
|
-
if (bookingNo) {
|
|
136
|
-
const booking = await Booking._Repo.findByPk(bookingNo, {
|
|
137
|
-
transaction: dbTransaction,
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
if (booking) {
|
|
141
|
-
return new Booking(booking.get({ plain: true }));
|
|
142
|
-
} else {
|
|
143
|
-
throw new Error('Booking not found');
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
return new Booking();
|
|
147
|
-
} catch (error) {
|
|
148
|
-
throw error;
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
public async create(
|
|
153
|
-
dbTransaction: any,
|
|
154
|
-
loginUser: LoginUser,
|
|
155
|
-
rentalPrice: RentalPrice,
|
|
156
|
-
) {
|
|
157
|
-
//This method will create new booking record.
|
|
158
|
-
try {
|
|
159
|
-
//Part 1: Check Privilege
|
|
160
|
-
const systemCode =
|
|
161
|
-
ApplicationConfig.getComponentConfigValue('system-code');
|
|
162
|
-
const isPrivileged = await loginUser.checkPrivileges(
|
|
163
|
-
systemCode,
|
|
164
|
-
'Booking - Create',
|
|
165
|
-
);
|
|
166
|
-
|
|
167
|
-
if (!isPrivileged) {
|
|
168
|
-
throw new ClassError(
|
|
169
|
-
'Booking',
|
|
170
|
-
'BookingErrMsg02',
|
|
171
|
-
"You do not have 'Booking - Create' privilege.",
|
|
172
|
-
);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
//Part 2: Booking Validation
|
|
176
|
-
//check if item and booking available
|
|
177
|
-
const isRentalAvailable = await Rental.isItemAvailable(
|
|
178
|
-
this.ItemId,
|
|
179
|
-
this.ItemType,
|
|
180
|
-
this._ScheduledStartDateTime,
|
|
181
|
-
this._ScheduledEndDateTime,
|
|
182
|
-
dbTransaction,
|
|
183
|
-
);
|
|
184
|
-
|
|
185
|
-
const isBookingAvailable = await Booking.isBookingItemAvailable(
|
|
186
|
-
dbTransaction,
|
|
187
|
-
this.ItemId,
|
|
188
|
-
this.ItemType,
|
|
189
|
-
this._ScheduledStartDateTime,
|
|
190
|
-
this._ScheduledEndDateTime,
|
|
191
|
-
);
|
|
192
|
-
|
|
193
|
-
if (!isRentalAvailable || !isBookingAvailable) {
|
|
194
|
-
throw new ClassError(
|
|
195
|
-
'Booking',
|
|
196
|
-
'BookingErrMsg02',
|
|
197
|
-
'Booking is not available for the item on the chosen date.',
|
|
198
|
-
);
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
//Part 3: Insert Booking & The Agreed Rental Price
|
|
202
|
-
const rp = await rentalPrice.create(loginUser, dbTransaction);
|
|
203
|
-
|
|
204
|
-
//Set below Booking attributes:
|
|
205
|
-
this.BookingNo = this.createId();
|
|
206
|
-
this.PriceId = rp.PriceId;
|
|
207
|
-
this._CreatedById = loginUser.ObjectId;
|
|
208
|
-
this._CreatedAt = DateTime.now().toJSDate();
|
|
209
|
-
this._UpdatedById = loginUser.ObjectId;
|
|
210
|
-
this._UpdatedAt = DateTime.now().toJSDate();
|
|
211
|
-
|
|
212
|
-
//call this class repo create
|
|
213
|
-
const data: IBookingAttr = {
|
|
214
|
-
BookingNo: this.BookingNo,
|
|
215
|
-
CustomerId: this.CustomerId,
|
|
216
|
-
CustomerType: this.CustomerType,
|
|
217
|
-
ItemId: this.ItemId,
|
|
218
|
-
ItemType: this.ItemType,
|
|
219
|
-
PriceId: this.PriceId,
|
|
220
|
-
ScheduledStartDateTime: this._ScheduledStartDateTime,
|
|
221
|
-
ScheduledEndDateTime: this._ScheduledEndDateTime,
|
|
222
|
-
BookingFee: this.BookingFee,
|
|
223
|
-
Status: this.Status,
|
|
224
|
-
CancelRemarks: this.CancelRemarks,
|
|
225
|
-
CreatedById: this._CreatedById,
|
|
226
|
-
CreatedAt: this._CreatedAt,
|
|
227
|
-
UpdatedById: this._UpdatedById,
|
|
228
|
-
UpdatedAt: this._UpdatedAt,
|
|
229
|
-
};
|
|
230
|
-
|
|
231
|
-
await Booking._Repo.create(data, {
|
|
232
|
-
transaction: dbTransaction,
|
|
233
|
-
});
|
|
234
|
-
|
|
235
|
-
//Part 4: Record Create Booking Activity
|
|
236
|
-
const activity = new Activity();
|
|
237
|
-
activity.ActivityId = activity.createId();
|
|
238
|
-
activity.Action = ActionEnum.ADD;
|
|
239
|
-
activity.Description = 'Add Booking';
|
|
240
|
-
activity.EntityId = this.BookingNo;
|
|
241
|
-
activity.EntityType = this.ObjectType;
|
|
242
|
-
activity.EntityValueBefore = JSON.stringify({});
|
|
243
|
-
activity.EntityValueAfter = JSON.stringify(data);
|
|
244
|
-
|
|
245
|
-
await activity.create(loginUser.ObjectId, dbTransaction);
|
|
246
|
-
|
|
247
|
-
return this;
|
|
248
|
-
} catch (error) {
|
|
249
|
-
throw error;
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
public static async isBookingItemAvailable(
|
|
254
|
-
dbTransaction: any,
|
|
255
|
-
itemId: string,
|
|
256
|
-
itemType: string,
|
|
257
|
-
startDateTime: Date,
|
|
258
|
-
endDateTime: Date,
|
|
259
|
-
) {
|
|
260
|
-
//This method will check if booking item available.
|
|
261
|
-
try {
|
|
262
|
-
//call this class repo findOne method
|
|
263
|
-
const booking = await Booking._Repo.findOne({
|
|
264
|
-
where: {
|
|
265
|
-
ItemId: itemId,
|
|
266
|
-
ItemType: itemType,
|
|
267
|
-
[Op.and]: [
|
|
268
|
-
{
|
|
269
|
-
ScheduledStartDateTime: {
|
|
270
|
-
[Op.lte]: endDateTime,
|
|
271
|
-
},
|
|
272
|
-
},
|
|
273
|
-
{
|
|
274
|
-
ScheduledEndDateTime: {
|
|
275
|
-
[Op.gte]: startDateTime,
|
|
276
|
-
},
|
|
277
|
-
},
|
|
278
|
-
],
|
|
279
|
-
},
|
|
280
|
-
transaction: dbTransaction,
|
|
281
|
-
});
|
|
282
|
-
|
|
283
|
-
//if booking record exists, return false.
|
|
284
|
-
if (booking) {
|
|
285
|
-
return false;
|
|
286
|
-
}
|
|
287
|
-
return true;
|
|
288
|
-
} catch (error) {
|
|
289
|
-
throw error;
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
public static async findAll(
|
|
294
|
-
dbTransaction: any,
|
|
295
|
-
page?: number,
|
|
296
|
-
row?: number,
|
|
297
|
-
search?: IBookingFindAllSearchAttr,
|
|
298
|
-
) {
|
|
299
|
-
try {
|
|
300
|
-
const queryObj: any = {};
|
|
301
|
-
|
|
302
|
-
let options: any = {
|
|
303
|
-
transaction: dbTransaction,
|
|
304
|
-
order: [['CreatedAt', 'DESC']],
|
|
305
|
-
};
|
|
306
|
-
|
|
307
|
-
if (page && row) {
|
|
308
|
-
options = {
|
|
309
|
-
...options,
|
|
310
|
-
limit: row,
|
|
311
|
-
offset: row * (page - 1),
|
|
312
|
-
};
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
if (search) {
|
|
316
|
-
Object.entries(search).forEach(([key, value]) => {
|
|
317
|
-
if (key === 'ScheduledStartDateTime') {
|
|
318
|
-
queryObj[key] = {
|
|
319
|
-
[Op.gte]: value,
|
|
320
|
-
};
|
|
321
|
-
} else if (key === 'ScheduledEndDateTime') {
|
|
322
|
-
queryObj[key] = {
|
|
323
|
-
[Op.lte]: value,
|
|
324
|
-
};
|
|
325
|
-
} else {
|
|
326
|
-
queryObj[key] = {
|
|
327
|
-
[Op.substring]: value,
|
|
328
|
-
};
|
|
329
|
-
}
|
|
330
|
-
});
|
|
331
|
-
|
|
332
|
-
options = {
|
|
333
|
-
...options,
|
|
334
|
-
where: queryObj,
|
|
335
|
-
};
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
return await Booking._Repo.findAndCountAll(options);
|
|
339
|
-
} catch (err) {
|
|
340
|
-
throw err;
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
}
|
|
1
|
+
import { ClassError, ObjectBase } from '@tomei/general';
|
|
2
|
+
import { BookingStatusEnum } from '../../enum/booking.enum';
|
|
3
|
+
import { IBookingAttr } from '../../interfaces/booking-attr.interface';
|
|
4
|
+
import { BookingRepository } from './booking.repository';
|
|
5
|
+
import { DateTime } from 'luxon';
|
|
6
|
+
import { LoginUser } from '@tomei/sso';
|
|
7
|
+
import { RentalPrice } from '../rental-price/rental-price';
|
|
8
|
+
import { ApplicationConfig } from '@tomei/config';
|
|
9
|
+
import { Op } from 'sequelize';
|
|
10
|
+
import { Rental } from '../rental/rental';
|
|
11
|
+
import { ActionEnum, Activity } from '@tomei/activity-history';
|
|
12
|
+
import { IBookingFindAllSearchAttr } from '../../interfaces/booking-find-all-search-attr.interface';
|
|
13
|
+
|
|
14
|
+
export class Booking extends ObjectBase {
|
|
15
|
+
ObjectId: string;
|
|
16
|
+
ObjectName: string;
|
|
17
|
+
ObjectType: string = 'Booking';
|
|
18
|
+
TableName = 'booking_Booking';
|
|
19
|
+
CustomerId: string;
|
|
20
|
+
CustomerType: string;
|
|
21
|
+
ItemId: string;
|
|
22
|
+
ItemType: string;
|
|
23
|
+
PriceId: string;
|
|
24
|
+
protected _ScheduledStartDateTime: Date;
|
|
25
|
+
protected _ScheduledEndDateTime: Date;
|
|
26
|
+
BookingFee: number;
|
|
27
|
+
Status: BookingStatusEnum;
|
|
28
|
+
CancelRemarks: string;
|
|
29
|
+
protected _CreatedById: string;
|
|
30
|
+
protected _CreatedAt: Date;
|
|
31
|
+
protected _UpdatedById: string;
|
|
32
|
+
protected _UpdatedAt: Date;
|
|
33
|
+
|
|
34
|
+
protected static _Repo = new BookingRepository();
|
|
35
|
+
|
|
36
|
+
get BookingNo(): string {
|
|
37
|
+
return this.ObjectId;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
set BookingNo(value: string) {
|
|
41
|
+
this.ObjectId = value;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
get CreatedById(): string {
|
|
45
|
+
return this._CreatedById;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
get CreatedAt(): Date {
|
|
49
|
+
return this._CreatedAt;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
get UpdatedById(): string {
|
|
53
|
+
return this._UpdatedById;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
get UpdatedAt(): Date {
|
|
57
|
+
return this._UpdatedAt;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
get ScheduledStartDateTime(): Date {
|
|
61
|
+
return this._ScheduledStartDateTime;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
get ScheduledEndDateTime(): Date {
|
|
65
|
+
return this._ScheduledEndDateTime;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
async setScheduledStartDateTime(datetime: Date) {
|
|
69
|
+
const dateTime = DateTime.fromJSDate(datetime);
|
|
70
|
+
const currentDateTime = DateTime.now();
|
|
71
|
+
if (dateTime <= currentDateTime) {
|
|
72
|
+
throw new ClassError(
|
|
73
|
+
'Booking',
|
|
74
|
+
'BookingErrMsg01',
|
|
75
|
+
'Booking must be for future date time.',
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
this._ScheduledStartDateTime = datetime;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
async setScheduledEndDateTime(datetime: Date) {
|
|
82
|
+
const dateTime = DateTime.fromJSDate(datetime);
|
|
83
|
+
const currentDateTime = DateTime.now();
|
|
84
|
+
if (dateTime <= currentDateTime) {
|
|
85
|
+
throw new ClassError(
|
|
86
|
+
'Booking',
|
|
87
|
+
'BookingErrMsg01',
|
|
88
|
+
'Booking must be for future date time.',
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (!this._ScheduledStartDateTime) {
|
|
93
|
+
throw new ClassError(
|
|
94
|
+
'Booking',
|
|
95
|
+
'BookingErrMsg01',
|
|
96
|
+
'Booking start date time must be set before setting end date time.',
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const startDateTime = DateTime.fromJSDate(this._ScheduledStartDateTime);
|
|
101
|
+
if (dateTime <= startDateTime) {
|
|
102
|
+
throw new ClassError(
|
|
103
|
+
'Booking',
|
|
104
|
+
'BookingErrMsg03',
|
|
105
|
+
'Booking end date time must be more than start date time.',
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
this._ScheduledEndDateTime = datetime;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
protected constructor(bookingAttr?: IBookingAttr) {
|
|
113
|
+
super();
|
|
114
|
+
if (bookingAttr) {
|
|
115
|
+
this.ObjectId = bookingAttr.BookingNo;
|
|
116
|
+
this.CustomerId = bookingAttr.CustomerId;
|
|
117
|
+
this.CustomerType = bookingAttr.CustomerType;
|
|
118
|
+
this.ItemId = bookingAttr.ItemId;
|
|
119
|
+
this.ItemType = bookingAttr.ItemType;
|
|
120
|
+
this.PriceId = bookingAttr.PriceId;
|
|
121
|
+
this._ScheduledStartDateTime = bookingAttr.ScheduledStartDateTime;
|
|
122
|
+
this._ScheduledEndDateTime = bookingAttr.ScheduledEndDateTime;
|
|
123
|
+
this.BookingFee = bookingAttr.BookingFee;
|
|
124
|
+
this.Status = bookingAttr.Status;
|
|
125
|
+
this.CancelRemarks = bookingAttr.CancelRemarks;
|
|
126
|
+
this._CreatedById = bookingAttr.CreatedById;
|
|
127
|
+
this._CreatedAt = bookingAttr.CreatedAt;
|
|
128
|
+
this._UpdatedById = bookingAttr.UpdatedById;
|
|
129
|
+
this._UpdatedAt = bookingAttr.UpdatedAt;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
public static async init(dbTransaction?: any, bookingNo?: string) {
|
|
134
|
+
try {
|
|
135
|
+
if (bookingNo) {
|
|
136
|
+
const booking = await Booking._Repo.findByPk(bookingNo, {
|
|
137
|
+
transaction: dbTransaction,
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
if (booking) {
|
|
141
|
+
return new Booking(booking.get({ plain: true }));
|
|
142
|
+
} else {
|
|
143
|
+
throw new Error('Booking not found');
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return new Booking();
|
|
147
|
+
} catch (error) {
|
|
148
|
+
throw error;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
public async create(
|
|
153
|
+
dbTransaction: any,
|
|
154
|
+
loginUser: LoginUser,
|
|
155
|
+
rentalPrice: RentalPrice,
|
|
156
|
+
) {
|
|
157
|
+
//This method will create new booking record.
|
|
158
|
+
try {
|
|
159
|
+
//Part 1: Check Privilege
|
|
160
|
+
const systemCode =
|
|
161
|
+
ApplicationConfig.getComponentConfigValue('system-code');
|
|
162
|
+
const isPrivileged = await loginUser.checkPrivileges(
|
|
163
|
+
systemCode,
|
|
164
|
+
'Booking - Create',
|
|
165
|
+
);
|
|
166
|
+
|
|
167
|
+
if (!isPrivileged) {
|
|
168
|
+
throw new ClassError(
|
|
169
|
+
'Booking',
|
|
170
|
+
'BookingErrMsg02',
|
|
171
|
+
"You do not have 'Booking - Create' privilege.",
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
//Part 2: Booking Validation
|
|
176
|
+
//check if item and booking available
|
|
177
|
+
const isRentalAvailable = await Rental.isItemAvailable(
|
|
178
|
+
this.ItemId,
|
|
179
|
+
this.ItemType,
|
|
180
|
+
this._ScheduledStartDateTime,
|
|
181
|
+
this._ScheduledEndDateTime,
|
|
182
|
+
dbTransaction,
|
|
183
|
+
);
|
|
184
|
+
|
|
185
|
+
const isBookingAvailable = await Booking.isBookingItemAvailable(
|
|
186
|
+
dbTransaction,
|
|
187
|
+
this.ItemId,
|
|
188
|
+
this.ItemType,
|
|
189
|
+
this._ScheduledStartDateTime,
|
|
190
|
+
this._ScheduledEndDateTime,
|
|
191
|
+
);
|
|
192
|
+
|
|
193
|
+
if (!isRentalAvailable || !isBookingAvailable) {
|
|
194
|
+
throw new ClassError(
|
|
195
|
+
'Booking',
|
|
196
|
+
'BookingErrMsg02',
|
|
197
|
+
'Booking is not available for the item on the chosen date.',
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
//Part 3: Insert Booking & The Agreed Rental Price
|
|
202
|
+
const rp = await rentalPrice.create(loginUser, dbTransaction);
|
|
203
|
+
|
|
204
|
+
//Set below Booking attributes:
|
|
205
|
+
this.BookingNo = this.createId();
|
|
206
|
+
this.PriceId = rp.PriceId;
|
|
207
|
+
this._CreatedById = loginUser.ObjectId;
|
|
208
|
+
this._CreatedAt = DateTime.now().toJSDate();
|
|
209
|
+
this._UpdatedById = loginUser.ObjectId;
|
|
210
|
+
this._UpdatedAt = DateTime.now().toJSDate();
|
|
211
|
+
|
|
212
|
+
//call this class repo create
|
|
213
|
+
const data: IBookingAttr = {
|
|
214
|
+
BookingNo: this.BookingNo,
|
|
215
|
+
CustomerId: this.CustomerId,
|
|
216
|
+
CustomerType: this.CustomerType,
|
|
217
|
+
ItemId: this.ItemId,
|
|
218
|
+
ItemType: this.ItemType,
|
|
219
|
+
PriceId: this.PriceId,
|
|
220
|
+
ScheduledStartDateTime: this._ScheduledStartDateTime,
|
|
221
|
+
ScheduledEndDateTime: this._ScheduledEndDateTime,
|
|
222
|
+
BookingFee: this.BookingFee,
|
|
223
|
+
Status: this.Status,
|
|
224
|
+
CancelRemarks: this.CancelRemarks,
|
|
225
|
+
CreatedById: this._CreatedById,
|
|
226
|
+
CreatedAt: this._CreatedAt,
|
|
227
|
+
UpdatedById: this._UpdatedById,
|
|
228
|
+
UpdatedAt: this._UpdatedAt,
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
await Booking._Repo.create(data, {
|
|
232
|
+
transaction: dbTransaction,
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
//Part 4: Record Create Booking Activity
|
|
236
|
+
const activity = new Activity();
|
|
237
|
+
activity.ActivityId = activity.createId();
|
|
238
|
+
activity.Action = ActionEnum.ADD;
|
|
239
|
+
activity.Description = 'Add Booking';
|
|
240
|
+
activity.EntityId = this.BookingNo;
|
|
241
|
+
activity.EntityType = this.ObjectType;
|
|
242
|
+
activity.EntityValueBefore = JSON.stringify({});
|
|
243
|
+
activity.EntityValueAfter = JSON.stringify(data);
|
|
244
|
+
|
|
245
|
+
await activity.create(loginUser.ObjectId, dbTransaction);
|
|
246
|
+
|
|
247
|
+
return this;
|
|
248
|
+
} catch (error) {
|
|
249
|
+
throw error;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
public static async isBookingItemAvailable(
|
|
254
|
+
dbTransaction: any,
|
|
255
|
+
itemId: string,
|
|
256
|
+
itemType: string,
|
|
257
|
+
startDateTime: Date,
|
|
258
|
+
endDateTime: Date,
|
|
259
|
+
) {
|
|
260
|
+
//This method will check if booking item available.
|
|
261
|
+
try {
|
|
262
|
+
//call this class repo findOne method
|
|
263
|
+
const booking = await Booking._Repo.findOne({
|
|
264
|
+
where: {
|
|
265
|
+
ItemId: itemId,
|
|
266
|
+
ItemType: itemType,
|
|
267
|
+
[Op.and]: [
|
|
268
|
+
{
|
|
269
|
+
ScheduledStartDateTime: {
|
|
270
|
+
[Op.lte]: endDateTime,
|
|
271
|
+
},
|
|
272
|
+
},
|
|
273
|
+
{
|
|
274
|
+
ScheduledEndDateTime: {
|
|
275
|
+
[Op.gte]: startDateTime,
|
|
276
|
+
},
|
|
277
|
+
},
|
|
278
|
+
],
|
|
279
|
+
},
|
|
280
|
+
transaction: dbTransaction,
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
//if booking record exists, return false.
|
|
284
|
+
if (booking) {
|
|
285
|
+
return false;
|
|
286
|
+
}
|
|
287
|
+
return true;
|
|
288
|
+
} catch (error) {
|
|
289
|
+
throw error;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
public static async findAll(
|
|
294
|
+
dbTransaction: any,
|
|
295
|
+
page?: number,
|
|
296
|
+
row?: number,
|
|
297
|
+
search?: IBookingFindAllSearchAttr,
|
|
298
|
+
) {
|
|
299
|
+
try {
|
|
300
|
+
const queryObj: any = {};
|
|
301
|
+
|
|
302
|
+
let options: any = {
|
|
303
|
+
transaction: dbTransaction,
|
|
304
|
+
order: [['CreatedAt', 'DESC']],
|
|
305
|
+
};
|
|
306
|
+
|
|
307
|
+
if (page && row) {
|
|
308
|
+
options = {
|
|
309
|
+
...options,
|
|
310
|
+
limit: row,
|
|
311
|
+
offset: row * (page - 1),
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
if (search) {
|
|
316
|
+
Object.entries(search).forEach(([key, value]) => {
|
|
317
|
+
if (key === 'ScheduledStartDateTime') {
|
|
318
|
+
queryObj[key] = {
|
|
319
|
+
[Op.gte]: value,
|
|
320
|
+
};
|
|
321
|
+
} else if (key === 'ScheduledEndDateTime') {
|
|
322
|
+
queryObj[key] = {
|
|
323
|
+
[Op.lte]: value,
|
|
324
|
+
};
|
|
325
|
+
} else {
|
|
326
|
+
queryObj[key] = {
|
|
327
|
+
[Op.substring]: value,
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
options = {
|
|
333
|
+
...options,
|
|
334
|
+
where: queryObj,
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
return await Booking._Repo.findAndCountAll(options);
|
|
339
|
+
} catch (err) {
|
|
340
|
+
throw err;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
}
|