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,
|
"name" varchar NOT NULL,
|
||||||
"password" varchar NOT NULL,
|
"password" varchar NOT NULL,
|
||||||
email varchar NOT NULL,
|
email varchar NOT NULL,
|
||||||
|
"createdAt" timestamp NOT NULL DEFAULT now(),
|
||||||
CONSTRAINT "users_pk" PRIMARY KEY (id),
|
CONSTRAINT "users_pk" PRIMARY KEY (id),
|
||||||
CONSTRAINT "users_email_unique" UNIQUE (email)
|
CONSTRAINT "users_email_unique" UNIQUE (email)
|
||||||
);
|
);
|
||||||
|
@ -18,7 +19,7 @@ export class InitSchema1695130227420 implements MigrationInterface {
|
||||||
"createdAt" timestamp NOT NULL DEFAULT now(),
|
"createdAt" timestamp NOT NULL DEFAULT now(),
|
||||||
"sourceUserId" int4 NULL,
|
"sourceUserId" int4 NULL,
|
||||||
"targetUserId" 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);
|
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 (
|
CREATE TABLE pairs (
|
||||||
id serial4 NOT NULL,
|
id serial4 NOT NULL,
|
||||||
|
"createdAt" timestamp NOT NULL DEFAULT now(),
|
||||||
CONSTRAINT "pairs_pk" PRIMARY KEY (id)
|
CONSTRAINT "pairs_pk" PRIMARY KEY (id)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -4,11 +4,17 @@ import { User } from 'src/users/entities/user.entity';
|
||||||
|
|
||||||
@Entity('pair-members')
|
@Entity('pair-members')
|
||||||
export class PairMember {
|
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)
|
@ManyToOne(() => Pair, (pair) => pair.pairMembers)
|
||||||
pair: Pair;
|
pair: Pair;
|
||||||
|
|
||||||
@PrimaryColumn('int', { name: 'userId' })
|
// @PrimaryColumn('int', { name: 'userId' })
|
||||||
@ManyToOne(() => User)
|
@ManyToOne(() => User)
|
||||||
user: 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';
|
import { PairMember } from './pair-member.entity';
|
||||||
|
|
||||||
@Entity('pairs')
|
@Entity('pairs')
|
||||||
|
@ -8,4 +13,7 @@ export class Pair {
|
||||||
|
|
||||||
@OneToMany(() => PairMember, (pairMember) => pairMember.pair)
|
@OneToMany(() => PairMember, (pairMember) => pairMember.pair)
|
||||||
pairMembers: PairMember[];
|
pairMembers: PairMember[];
|
||||||
|
|
||||||
|
@CreateDateColumn({ type: 'timestamp' })
|
||||||
|
createdAt: Date;
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,17 +30,19 @@ export class PairsService {
|
||||||
async (manager) => {
|
async (manager) => {
|
||||||
const pair = this.pairsRepository.create();
|
const pair = this.pairsRepository.create();
|
||||||
await manager.save(pair);
|
await manager.save(pair);
|
||||||
|
|
||||||
const pairMembers = this.pairMembersRepository.create([
|
const pairMembers = this.pairMembersRepository.create([
|
||||||
{
|
{
|
||||||
pair,
|
pairId: pair.id,
|
||||||
user: { id: userIds[0] },
|
userId: userIds[0],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pair,
|
pairId: pair.id,
|
||||||
user: { id: userIds[1] },
|
userId: userIds[1],
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
await manager.save(pairMembers);
|
await manager.save(pairMembers);
|
||||||
|
|
||||||
return pair;
|
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 { SwipesService } from './swipes.service';
|
||||||
import { UsersModule } from 'src/users/users.module';
|
import { UsersModule } from 'src/users/users.module';
|
||||||
import { PairsModule } from 'src/pairs/pairs.module';
|
import { PairsModule } from 'src/pairs/pairs.module';
|
||||||
|
import { SwipesController } from './swipes.controller';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [TypeOrmModule.forFeature([Swipe]), UsersModule, PairsModule],
|
imports: [TypeOrmModule.forFeature([Swipe]), UsersModule, PairsModule],
|
||||||
providers: [SwipesService],
|
providers: [SwipesService],
|
||||||
|
controllers: [SwipesController],
|
||||||
})
|
})
|
||||||
export class SwipesModule {}
|
export class SwipesModule {}
|
||||||
|
|
|
@ -15,37 +15,53 @@ export class SwipesService {
|
||||||
private readonly pairsService: PairsService,
|
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(
|
async createSwipe(
|
||||||
sourceUserId: number,
|
sourceUserId: number,
|
||||||
targetUserId: number,
|
targetUserId: number,
|
||||||
liked: boolean,
|
liked: boolean,
|
||||||
) {
|
) {
|
||||||
const users = await this.usersService.getByIds([
|
const sourceUser = await this.usersService.getById(sourceUserId);
|
||||||
sourceUserId,
|
const targetUser = await this.usersService.getById(targetUserId);
|
||||||
targetUserId,
|
if (!sourceUser || !targetUser) {
|
||||||
]);
|
|
||||||
if (users.length !== 2) {
|
|
||||||
throw new UserIdNotExistsException();
|
throw new UserIdNotExistsException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const existedSwipe = await this.getSwipe(sourceUserId, targetUserId, liked);
|
||||||
|
if (existedSwipe) {
|
||||||
|
return existedSwipe;
|
||||||
|
}
|
||||||
|
|
||||||
const swipe = this.swipesRepository.create({
|
const swipe = this.swipesRepository.create({
|
||||||
sourceUser: { id: sourceUserId },
|
sourceUser: { id: sourceUserId },
|
||||||
targetUser: { id: targetUserId },
|
targetUser: { id: targetUserId },
|
||||||
liked,
|
liked,
|
||||||
});
|
});
|
||||||
|
|
||||||
await this.swipesRepository.save(swipe);
|
await this.swipesRepository.save(swipe);
|
||||||
|
|
||||||
if (liked) {
|
if (liked) {
|
||||||
const answeringLikeSwipe = await this.swipesRepository.findBy({
|
const answeringLikeSwipe = await this.getSwipe(
|
||||||
sourceUser: { id: targetUserId },
|
targetUserId,
|
||||||
targetUser: { id: sourceUserId },
|
sourceUserId,
|
||||||
});
|
true,
|
||||||
|
);
|
||||||
|
|
||||||
if (answeringLikeSwipe) {
|
if (answeringLikeSwipe) {
|
||||||
await this.pairsService.createPair([sourceUserId, targetUserId]); // TODO use transaction?
|
await this.pairsService.createPair([sourceUserId, targetUserId]); // TODO use transaction?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return swipe;
|
return this.getSwipeById(swipe.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getSwipesByUser(sourceUserId: number) {
|
async getSwipesByUser(sourceUserId: number) {
|
||||||
|
@ -53,6 +69,39 @@ export class SwipesService {
|
||||||
if (!user) {
|
if (!user) {
|
||||||
throw new UserIdNotExistsException();
|
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 { Swipe } from 'src/swipes/entities/swipe.entity';
|
||||||
import { Column, Entity, OneToMany, PrimaryGeneratedColumn } from 'typeorm';
|
import {
|
||||||
|
Column,
|
||||||
|
CreateDateColumn,
|
||||||
|
Entity,
|
||||||
|
OneToMany,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
} from 'typeorm';
|
||||||
|
|
||||||
@Entity('users')
|
@Entity('users')
|
||||||
export class User {
|
export class User {
|
||||||
|
@ -10,6 +17,7 @@ export class User {
|
||||||
name: string;
|
name: string;
|
||||||
|
|
||||||
@Column()
|
@Column()
|
||||||
|
@Exclude()
|
||||||
password: string;
|
password: string;
|
||||||
|
|
||||||
@Column({ unique: true })
|
@Column({ unique: true })
|
||||||
|
@ -20,4 +28,7 @@ export class User {
|
||||||
|
|
||||||
@OneToMany(() => Swipe, (swipe) => swipe.targetUser)
|
@OneToMany(() => Swipe, (swipe) => swipe.targetUser)
|
||||||
swiped: Swipe[];
|
swiped: Swipe[];
|
||||||
|
|
||||||
|
@CreateDateColumn({ type: 'timestamp' })
|
||||||
|
createdAt: Date;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,10 @@ export class UsersService {
|
||||||
}
|
}
|
||||||
|
|
||||||
async getById(id: number) {
|
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) {
|
if (!user) {
|
||||||
throw new UserIdNotExistsException();
|
throw new UserIdNotExistsException();
|
||||||
}
|
}
|
||||||
|
@ -41,6 +44,8 @@ export class UsersService {
|
||||||
|
|
||||||
async create(userData: CreateUserDto) {
|
async create(userData: CreateUserDto) {
|
||||||
const user = this.usersRepository.create(userData);
|
const user = this.usersRepository.create(userData);
|
||||||
|
console.log('user', user);
|
||||||
|
|
||||||
await this.usersRepository.save(user);
|
await this.usersRepository.save(user);
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue