@@ -81,35 +81,71 @@ export class LockersService {
81
81
return await this . lockerRepository . findOne ( { where : { id } } ) ;
82
82
}
83
83
84
- async getUserLocker ( userAzureId : string , userAccessToken : string ) {
84
+ async getUserLockers ( userAzureId : string , userAccessToken : string ) {
85
85
const user : UserPassEntity = await this . passService . getUserFromAzureId (
86
86
userAzureId ,
87
87
userAccessToken ,
88
88
) ;
89
89
if ( ! user ) {
90
90
throw new NotFoundException ( 'User not found' ) ;
91
91
}
92
- return await this . getUsersActiveLocker ( user ) ;
92
+ return await this . getUsersActiveLockers ( user , false ) ;
93
93
}
94
94
95
- async getUsersActiveLocker (
95
+ async getUsersActiveLockers (
96
96
user : UserPassEntity ,
97
- ) : Promise < LockerEntity | null > {
98
- const locker = await this . lockersUsersRepository
97
+ countOnly : true ,
98
+ ) : Promise < number > ;
99
+ async getUsersActiveLockers (
100
+ user : UserPassEntity ,
101
+ countOnly : false ,
102
+ ) : Promise < LockerEntity [ ] > ;
103
+
104
+ async getUsersActiveLockers (
105
+ user : UserPassEntity ,
106
+ countOnly : boolean ,
107
+ ) : Promise < LockerEntity [ ] | number > {
108
+ const data = this . lockersUsersRepository
99
109
. createQueryBuilder ( 'lockers_users' )
100
110
. select ( 'locker_id' )
101
111
. where ( 'user_id = :user_id' , { user_id : user . id } )
102
112
. andWhere ( 'start_time < NOW()' )
103
113
. andWhere ( '(end_time > NOW() OR end_time IS NULL)' )
104
- . orderBy ( 'start_time' , 'DESC' )
105
- . limit ( 1 )
106
- . getRawOne ( ) ;
114
+ . orderBy ( 'start_time' , 'DESC' ) ;
107
115
108
- if ( ! locker || ! locker . locker_id ) {
109
- return null ;
116
+ if ( countOnly ) {
117
+ return await data . getCount ( ) ;
110
118
}
111
119
112
- return await this . getLockerById ( locker . locker_id ) ;
120
+ const lockers = await data . getRawMany ( ) ;
121
+ const promises = lockers . map ( ( locker ) =>
122
+ this . getLockerById ( locker . locker_id ) ,
123
+ ) ;
124
+ const result = await Promise . allSettled ( promises ) ;
125
+
126
+ return result
127
+ . map ( ( r ) => {
128
+ if ( r . status === 'fulfilled' ) {
129
+ return r . value ;
130
+ }
131
+ return null ;
132
+ } )
133
+ . filter ( ( r ) : r is LockerEntity => r !== null ) ;
134
+ }
135
+
136
+ async isUserUsingLocker (
137
+ user : UserPassEntity ,
138
+ lockerId : number ,
139
+ ) : Promise < boolean > {
140
+ const result : number = await this . lockersUsersRepository
141
+ . createQueryBuilder ( 'lu' )
142
+ . where ( 'lu.user_id = :user_id' , { user_id : user . id } )
143
+ . andWhere ( 'lu.locker_id = :locker_id' , { locker_id : lockerId } )
144
+ . andWhere ( 'lu.start_time < NOW()' )
145
+ . andWhere ( '(lu.end_time > NOW() OR lu.end_time IS NULL)' )
146
+ . getCount ( ) ;
147
+
148
+ return result > 0 ;
113
149
}
114
150
115
151
// Open locker or assign locker to
@@ -125,14 +161,20 @@ export class LockersService {
125
161
if ( ! user ) {
126
162
throw new NotFoundException ( 'User not found' ) ;
127
163
}
128
- const activeLocker = await this . getUsersActiveLocker ( user ) ;
129
- if ( activeLocker ) {
130
- const success = await this . openLocker ( activeLocker ) ;
131
- if ( ! success ) {
132
- throw new InternalServerErrorException ( 'Failed to open locker' ) ;
133
- }
164
+
165
+ // Check if user is already using locker
166
+ const isUserUsingLocker = await this . isUserUsingLocker ( user , lockerId ) ;
167
+ if ( isUserUsingLocker ) {
168
+ await this . openLockerById ( lockerId ) ;
134
169
return ;
135
170
}
171
+
172
+ // Check if user lockers limit is reached
173
+ const userLockersCount = await this . getUsersActiveLockers ( user , true ) ;
174
+ if ( userLockersCount >= 2 ) {
175
+ throw new NotFoundException ( 'You have reached the limit of lockers' ) ;
176
+ }
177
+
136
178
const selectedLocker = await this . getLockerById ( lockerId ) ;
137
179
if ( ! selectedLocker ) {
138
180
throw new NotFoundException ( 'Locker not found' ) ;
@@ -163,18 +205,29 @@ export class LockersService {
163
205
}
164
206
165
207
// End locker session
166
- async endLocker ( userAzureId : string , userAccessToken : string ) {
208
+ async endLocker (
209
+ userAzureId : string ,
210
+ userAccessToken : string ,
211
+ lockerId : number ,
212
+ ) {
167
213
const user : UserPassEntity = await this . passService . getUserFromAzureId (
168
214
userAzureId ,
169
215
userAccessToken ,
170
216
) ;
171
217
if ( ! user ) {
172
218
throw new NotFoundException ( 'User not found' ) ;
173
219
}
174
- const activeLocker = await this . getUsersActiveLocker ( user ) ;
220
+
221
+ const isUserUsingLocker = await this . isUserUsingLocker ( user , lockerId ) ;
222
+ if ( ! isUserUsingLocker ) {
223
+ throw new NotFoundException ( 'User is not using this locker' ) ;
224
+ }
225
+
226
+ const activeLocker = await this . getLockerById ( lockerId ) ;
175
227
if ( ! activeLocker ) {
176
- throw new NotFoundException ( 'User does not have an active locker ' ) ;
228
+ throw new NotFoundException ( 'Locker not found ' ) ;
177
229
}
230
+
178
231
const success = await this . openLocker ( activeLocker ) ;
179
232
if ( ! success ) {
180
233
throw new InternalServerErrorException ( 'Failed to open locker' ) ;
0 commit comments