fix migration, add create swipe route
This commit is contained in:
parent
bf38ec5355
commit
06cf4b129f
|
@ -8,6 +8,7 @@ export class InitSchema1695130227420 implements MigrationInterface {
|
|||
"name" varchar NOT NULL,
|
||||
"password" varchar NOT NULL,
|
||||
email varchar NOT NULL,
|
||||
"createdAt" timestamp NOT NULL DEFAULT now(),
|
||||
CONSTRAINT "users_pk" PRIMARY KEY (id),
|
||||
CONSTRAINT "users_email_unique" UNIQUE (email)
|
||||
);
|
||||
|
@ -18,7 +19,7 @@ export class InitSchema1695130227420 implements MigrationInterface {
|
|||
"createdAt" timestamp NOT NULL DEFAULT now(),
|
||||
"sourceUserId" int4 NULL,
|
||||
"targetUserId" int4 NULL,
|
||||
CONSTRAINT "PK_bb38af5831e2c084a78e3622ff6" PRIMARY KEY (id)
|
||||
CONSTRAINT "swipes_pk" PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
ALTER TABLE swipes ADD CONSTRAINT "swipes_target_user_fk" FOREIGN KEY ("targetUserId") REFERENCES users(id);
|
||||
|
@ -26,6 +27,7 @@ export class InitSchema1695130227420 implements MigrationInterface {
|
|||
|
||||
CREATE TABLE pairs (
|
||||
id serial4 NOT NULL,
|
||||
"createdAt" timestamp NOT NULL DEFAULT now(),
|
||||
CONSTRAINT "pairs_pk" PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
|
|
|
@ -4,11 +4,17 @@ import { User } from 'src/users/entities/user.entity';
|
|||
|
||||
@Entity('pair-members')
|
||||
export class PairMember {
|
||||
@PrimaryColumn('int', { name: 'pairId' })
|
||||
@PrimaryColumn({ type: 'int4', name: 'pairId' })
|
||||
pairId: number;
|
||||
|
||||
@PrimaryColumn({ type: 'int', name: 'userId' })
|
||||
userId: number;
|
||||
|
||||
// @PrimaryColumn('int', { name: 'pairId' })
|
||||
@ManyToOne(() => Pair, (pair) => pair.pairMembers)
|
||||
pair: Pair;
|
||||
|
||||
@PrimaryColumn('int', { name: 'userId' })
|
||||
// @PrimaryColumn('int', { name: 'userId' })
|
||||
@ManyToOne(() => User)
|
||||
user: User;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,9 @@
|
|||
import { Entity, OneToMany, PrimaryGeneratedColumn } from 'typeorm';
|
||||
import {
|
||||
CreateDateColumn,
|
||||
Entity,
|
||||
OneToMany,
|
||||
PrimaryGeneratedColumn,
|
||||
} from 'typeorm';
|
||||
import { PairMember } from './pair-member.entity';
|
||||
|
||||
@Entity('pairs')
|
||||
|
@ -8,4 +13,7 @@ export class Pair {
|
|||
|
||||
@OneToMany(() => PairMember, (pairMember) => pairMember.pair)
|
||||
pairMembers: PairMember[];
|
||||
|
||||
@CreateDateColumn({ type: 'timestamp' })
|
||||
createdAt: Date;
|
||||
}
|
||||
|
|
|
@ -30,17 +30,19 @@ export class PairsService {
|
|||
async (manager) => {
|
||||
const pair = this.pairsRepository.create();
|
||||
await manager.save(pair);
|
||||
|
||||
const pairMembers = this.pairMembersRepository.create([
|
||||
{
|
||||
pair,
|
||||
user: { id: userIds[0] },
|
||||
pairId: pair.id,
|
||||
userId: userIds[0],
|
||||
},
|
||||
{
|
||||
pair,
|
||||
user: { id: userIds[1] },
|
||||
pairId: pair.id,
|
||||
userId: userIds[1],
|
||||
},
|
||||
]);
|
||||
await manager.save(pairMembers);
|
||||
|
||||
return pair;
|
||||
},
|
||||
);
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsBoolean, IsNumber } from 'class-validator';
|
||||
|
||||
export class CreateSwipeDto {
|
||||
@ApiProperty()
|
||||
@IsNumber()
|
||||
userId: number;
|
||||
|
||||
@ApiProperty()
|
||||
@IsBoolean()
|
||||
liked: boolean;
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { User } from 'src/users/entities/user.entity';
|
||||
|
||||
export class CreateSwipeResponseDto {
|
||||
@ApiProperty()
|
||||
id: number;
|
||||
|
||||
@ApiProperty()
|
||||
sourceUser: Pick<User, 'id' | 'name' | 'email'>;
|
||||
|
||||
@ApiProperty()
|
||||
targetUser: Pick<User, 'id' | 'name' | 'email'>;
|
||||
|
||||
@ApiProperty()
|
||||
liked: boolean;
|
||||
|
||||
@ApiProperty()
|
||||
createdAt: Date;
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
import {
|
||||
Body,
|
||||
Controller,
|
||||
HttpCode,
|
||||
Post,
|
||||
Req,
|
||||
UseGuards,
|
||||
} from '@nestjs/common';
|
||||
import { ApiBody, ApiCreatedResponse, ApiTags } from '@nestjs/swagger';
|
||||
import { SwipesService } from './swipes.service';
|
||||
import { CreateSwipeDto } from './dto/create-swipe.dto';
|
||||
import JwtAuthGuard from 'src/auth/guards/jwt-auth.guard';
|
||||
import { RequestWithUser } from 'src/auth/interfaces/request-with-user.interface';
|
||||
import { CreateSwipeResponseDto } from './dto/create-swipe.response.dto';
|
||||
|
||||
@ApiTags('swipes')
|
||||
@Controller('swipes')
|
||||
export class SwipesController {
|
||||
constructor(private readonly swipesService: SwipesService) {}
|
||||
|
||||
@HttpCode(201)
|
||||
@Post()
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@ApiBody({ type: CreateSwipeDto })
|
||||
@ApiCreatedResponse({ type: CreateSwipeResponseDto })
|
||||
async create(
|
||||
@Req() req: RequestWithUser,
|
||||
@Body() createData: CreateSwipeDto,
|
||||
) {
|
||||
const swipe = await this.swipesService.createSwipe(
|
||||
req.user.id,
|
||||
createData.userId,
|
||||
createData.liked,
|
||||
);
|
||||
|
||||
return swipe;
|
||||
}
|
||||
}
|
|
@ -4,9 +4,11 @@ import { Swipe } from './entities/swipe.entity';
|
|||
import { SwipesService } from './swipes.service';
|
||||
import { UsersModule } from 'src/users/users.module';
|
||||
import { PairsModule } from 'src/pairs/pairs.module';
|
||||
import { SwipesController } from './swipes.controller';
|
||||
|
||||
@Module({
|
||||
imports: [TypeOrmModule.forFeature([Swipe]), UsersModule, PairsModule],
|
||||
providers: [SwipesService],
|
||||
controllers: [SwipesController],
|
||||
})
|
||||
export class SwipesModule {}
|
||||
|
|
|
@ -15,37 +15,53 @@ export class SwipesService {
|
|||
private readonly pairsService: PairsService,
|
||||
) {}
|
||||
|
||||
get select() {
|
||||
return {
|
||||
id: true,
|
||||
createdAt: true,
|
||||
liked: true,
|
||||
sourceUser: { id: true, email: true, name: true },
|
||||
targetUser: { id: true, email: true, name: true },
|
||||
};
|
||||
}
|
||||
|
||||
async createSwipe(
|
||||
sourceUserId: number,
|
||||
targetUserId: number,
|
||||
liked: boolean,
|
||||
) {
|
||||
const users = await this.usersService.getByIds([
|
||||
sourceUserId,
|
||||
targetUserId,
|
||||
]);
|
||||
if (users.length !== 2) {
|
||||
const sourceUser = await this.usersService.getById(sourceUserId);
|
||||
const targetUser = await this.usersService.getById(targetUserId);
|
||||
if (!sourceUser || !targetUser) {
|
||||
throw new UserIdNotExistsException();
|
||||
}
|
||||
|
||||
const existedSwipe = await this.getSwipe(sourceUserId, targetUserId, liked);
|
||||
if (existedSwipe) {
|
||||
return existedSwipe;
|
||||
}
|
||||
|
||||
const swipe = this.swipesRepository.create({
|
||||
sourceUser: { id: sourceUserId },
|
||||
targetUser: { id: targetUserId },
|
||||
liked,
|
||||
});
|
||||
|
||||
await this.swipesRepository.save(swipe);
|
||||
|
||||
if (liked) {
|
||||
const answeringLikeSwipe = await this.swipesRepository.findBy({
|
||||
sourceUser: { id: targetUserId },
|
||||
targetUser: { id: sourceUserId },
|
||||
});
|
||||
const answeringLikeSwipe = await this.getSwipe(
|
||||
targetUserId,
|
||||
sourceUserId,
|
||||
true,
|
||||
);
|
||||
|
||||
if (answeringLikeSwipe) {
|
||||
await this.pairsService.createPair([sourceUserId, targetUserId]); // TODO use transaction?
|
||||
}
|
||||
}
|
||||
|
||||
return swipe;
|
||||
return this.getSwipeById(swipe.id);
|
||||
}
|
||||
|
||||
async getSwipesByUser(sourceUserId: number) {
|
||||
|
@ -53,6 +69,39 @@ export class SwipesService {
|
|||
if (!user) {
|
||||
throw new UserIdNotExistsException();
|
||||
}
|
||||
return this.swipesRepository.findBy({ sourceUser: { id: sourceUserId } });
|
||||
return this.swipesRepository.find({
|
||||
where: { sourceUser: { id: sourceUserId } },
|
||||
select: this.select,
|
||||
relations: {
|
||||
sourceUser: true,
|
||||
targetUser: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async getSwipe(sourceUserId: number, targetUserId: number, liked: boolean) {
|
||||
return this.swipesRepository.findOne({
|
||||
where: {
|
||||
sourceUser: { id: sourceUserId },
|
||||
targetUser: { id: targetUserId },
|
||||
liked,
|
||||
},
|
||||
select: this.select,
|
||||
relations: {
|
||||
sourceUser: true,
|
||||
targetUser: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async getSwipeById(id: number) {
|
||||
return this.swipesRepository.findOne({
|
||||
where: { id },
|
||||
select: this.select,
|
||||
relations: {
|
||||
sourceUser: true,
|
||||
targetUser: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
import { Exclude } from 'class-transformer';
|
||||
import { Swipe } from 'src/swipes/entities/swipe.entity';
|
||||
import { Column, Entity, OneToMany, PrimaryGeneratedColumn } from 'typeorm';
|
||||
import {
|
||||
Column,
|
||||
CreateDateColumn,
|
||||
Entity,
|
||||
OneToMany,
|
||||
PrimaryGeneratedColumn,
|
||||
} from 'typeorm';
|
||||
|
||||
@Entity('users')
|
||||
export class User {
|
||||
|
@ -10,6 +17,7 @@ export class User {
|
|||
name: string;
|
||||
|
||||
@Column()
|
||||
@Exclude()
|
||||
password: string;
|
||||
|
||||
@Column({ unique: true })
|
||||
|
@ -20,4 +28,7 @@ export class User {
|
|||
|
||||
@OneToMany(() => Swipe, (swipe) => swipe.targetUser)
|
||||
swiped: Swipe[];
|
||||
|
||||
@CreateDateColumn({ type: 'timestamp' })
|
||||
createdAt: Date;
|
||||
}
|
||||
|
|
|
@ -28,7 +28,10 @@ export class UsersService {
|
|||
}
|
||||
|
||||
async getById(id: number) {
|
||||
const user = await this.usersRepository.findOneBy({ id });
|
||||
const user = await this.usersRepository.findOne({
|
||||
where: { id },
|
||||
select: { id: true, email: true, name: true, swipes: true, swiped: true },
|
||||
});
|
||||
if (!user) {
|
||||
throw new UserIdNotExistsException();
|
||||
}
|
||||
|
@ -41,6 +44,8 @@ export class UsersService {
|
|||
|
||||
async create(userData: CreateUserDto) {
|
||||
const user = this.usersRepository.create(userData);
|
||||
console.log('user', user);
|
||||
|
||||
await this.usersRepository.save(user);
|
||||
return user;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue