Skip to content

Commit 1de2ad7

Browse files
authored
Merge pull request #279 from SCVApp/master
updated api for the app lockers
2 parents c452810 + 79f8741 commit 1de2ad7

File tree

6 files changed

+74
-32
lines changed

6 files changed

+74
-32
lines changed

db_migrations/locker_function.sql

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,9 @@
11
CREATE OR REPLACE FUNCTION check_locker_availability()
22
RETURNS TRIGGER AS $$
3-
DECLARE
4-
old_controller_id INT;
5-
new_locker_id INT;
63
BEGIN
74
IF OLD.locker_id IS NULL OR NEW.locker_id != OLD.locker_id THEN
85
IF EXISTS(SELECT 1 FROM lockers_users WHERE locker_id = NEW.locker_id AND start_time < NOW() AND (end_time IS NULL OR end_time > NOW())) THEN
9-
SELECT controller_id INTO old_controller_id FROM lockers WHERE id = NEW.locker_id;
10-
SELECT id INTO new_locker_id FROM lockers WHERE controller_id = old_controller_id AND id NOT IN (SELECT locker_id FROM lockers_users WHERE start_time < NOW() AND (end_time IS NULL OR end_time > NOW()));
11-
IF new_locker_id IS NULL THEN
12-
RAISE EXCEPTION 'No available lockers';
13-
ELSE
14-
NEW.locker_id := new_locker_id;
15-
END IF;
6+
RAISE EXCEPTION 'This locker is already in use';
167
END IF;
178
END IF;
189

src/app.module.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,10 @@ export class AppModule implements NestModule {
9696
path: 'lockers/my',
9797
method: RequestMethod.GET,
9898
},
99+
{
100+
path: 'lockers/controller/:controllerId',
101+
method: RequestMethod.GET,
102+
},
99103
);
100104
consumer
101105
.apply(AdminMiddleware)
@@ -117,7 +121,7 @@ export class AppModule implements NestModule {
117121
'pass',
118122
'notification',
119123
{
120-
path: 'lockers/controller/:controllerId',
124+
path: 'lockers/controller/:controllerId/admin',
121125
method: RequestMethod.GET,
122126
},
123127
{

src/lockers/dto/openLocker.dto.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { IsNotEmpty, IsNumberString } from 'class-validator';
33
export class OpenLockerDto {
44
@IsNotEmpty()
55
@IsNumberString()
6-
controllerId: number;
6+
lockerId: number;
77

88
azure_id: string;
99
access_token: string;

src/lockers/lockers.controller.ts

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,10 @@ export class LockersController {
4545
}
4646

4747
/*
48-
Get all lockers by controller id
48+
Get all lockers by controller id for admins
4949
*/
50-
@Get('controller/:controllerId')
51-
async getLockersByControllerId(
50+
@Get('controller/:controllerId/admin')
51+
async getLockersByControllerIdAdmin(
5252
@Param('controllerId', ParseIntPipe) controllerId: number,
5353
@Res() res: Response,
5454
) {
@@ -58,6 +58,21 @@ export class LockersController {
5858
return res.status(200).json(lockers);
5959
}
6060

61+
/*
62+
Get all lockers by controller id for users
63+
*/
64+
@Get('controller/:controllerId')
65+
async getLockersByControllerId(
66+
@Param('controllerId', ParseIntPipe) controllerId: number,
67+
@Res() res: Response,
68+
) {
69+
const lockers =
70+
await this.lockersService.getLockersByControllerIdWithStatus(
71+
controllerId,
72+
);
73+
return res.status(200).json(lockers);
74+
}
75+
6176
/*
6277
User requests to open locker if user currently does not have a locker it will be assigned to him if locker is available
6378
If user has a locker assigned to him it will be opened
@@ -69,7 +84,7 @@ export class LockersController {
6984
await this.lockersService.openOrAssignLocker(
7085
userAzureId,
7186
userAccessToken,
72-
data.controllerId,
87+
data.lockerId,
7388
);
7489

7590
return res.status(200).json({ message: 'Locker opened' });

src/lockers/lockers.service.ts

Lines changed: 43 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { UserPassEntity } from 'src/pass/entities/passUser.entity';
1818
import { ControllerWithActiveLockerCount } from './types/controllerWithActiveLockerCount.type';
1919
import { LockerWithActiveUser } from './types/lockerWithActiveUser.type';
2020
import { NotificationService } from 'src/notification/notification.service';
21+
import { LockerWithStatus } from './types/lockerWithStatus.type';
2122

2223
@Injectable()
2324
export class LockersService {
@@ -115,7 +116,7 @@ export class LockersService {
115116
async openOrAssignLocker(
116117
userAzureId: string,
117118
userAccessToken: string,
118-
controllerId: number,
119+
lockerId: number,
119120
) {
120121
const user: UserPassEntity = await this.passService.getUserFromAzureId(
121122
userAzureId,
@@ -132,34 +133,29 @@ export class LockersService {
132133
}
133134
return;
134135
}
135-
const firstAvailableLocker = await this.getFirstAvailableLocker(
136-
controllerId,
137-
);
138-
if (!firstAvailableLocker) {
139-
throw new NotFoundException('No lockers available');
136+
const selectedLocker = await this.getLockerById(lockerId);
137+
if (!selectedLocker) {
138+
throw new NotFoundException('Locker not found');
140139
}
141140

142-
// This is the check from db, becouse we have a trigger on lockers_users table and if we insert already used locker, it will change the locker with the first available one
141+
// This is the check from db, becouse we have a trigger on lockers_users table and if we insert already used locker
143142
const result = await this.lockersUsersRepository
144143
.insert({
145144
user,
146-
locker: firstAvailableLocker,
145+
locker: selectedLocker,
147146
})
148147
.catch(() => {
149-
throw new InternalServerErrorException('No lockers available');
148+
throw new NotFoundException('This locker is already in use');
150149
});
151150
if (!result) {
152-
throw new NotFoundException('No lockers available');
153-
}
154-
const assignedLocker = await this.getUsersActiveLocker(user);
155-
if (!assignedLocker) {
156-
throw new NotFoundException('No lockers available');
151+
throw new NotFoundException('This locker is already in use');
157152
}
158-
const success = await this.openLocker(assignedLocker);
153+
154+
const success = await this.openLocker(selectedLocker);
159155
if (!success) {
160156
await this.lockersUsersRepository.delete({
161157
user,
162-
locker: assignedLocker,
158+
locker: selectedLocker,
163159
});
164160
throw new InternalServerErrorException('Failed to open locker');
165161
}
@@ -308,6 +304,37 @@ export class LockersService {
308304
});
309305
}
310306

307+
async getLockersByControllerIdWithStatus(
308+
cotrollerId: number,
309+
): Promise<LockerWithStatus[]> {
310+
const lockersData = await this.lockerRepository
311+
.createQueryBuilder('lockers')
312+
.leftJoinAndSelect(
313+
'lockers_users',
314+
'lockers_users',
315+
`lockers.id = lockers_users.locker_id
316+
AND lockers_users.start_time < NOW()
317+
AND (lockers_users.end_time > NOW() OR lockers_users.end_time IS NULL)`,
318+
)
319+
.where('lockers.controller_id = :controller_id', {
320+
controller_id: cotrollerId,
321+
})
322+
.select('lockers.id', 'lockerId')
323+
.addSelect('lockers.identifier', 'identifier')
324+
.addSelect('lockers_users.user_id', 'userId')
325+
.orderBy('lockers.position', 'ASC')
326+
.getRawMany();
327+
328+
return lockersData.map((data) => {
329+
const obj: LockerWithStatus = {
330+
id: data.lockerId,
331+
identifier: data.identifier,
332+
used: data.userId !== null,
333+
};
334+
return obj;
335+
});
336+
}
337+
311338
async signJwtToken(controllerToken: string, lockerId: string) {
312339
return this.jwtService.sign(
313340
{ controllerToken, lockerId },
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export class LockerWithStatus {
2+
id: number;
3+
identifier: string;
4+
used: boolean;
5+
}

0 commit comments

Comments
 (0)