nestjsx / crud

NestJs CRUD for RESTful APIs
https://github.com/nestjsx/crud/wiki
MIT License
4.04k stars 534 forks source link

The base update function from CrudController used with the Join parameter settled to eager doesn't work well #617

Open fabiomsrs opened 3 years ago

fabiomsrs commented 3 years ago

I have an optional OneToOne relation between Class User and Profile. I've got two instances of Profile one has a user and the other hasn't. image

Ok, here is the problem, when I try to execute the 'createOne()' using the existing profile that hasn't a User and the parameter Join User is settled to eager, the function 'this.base.updateOneBase(req, profile);' executes an update in the profile trying to insert the User of the other existing profile without me sending this user, and then an error is returned due to the OneToOne restriction.

image

image

image

AbstractEntity:

export abstract class AbstractEntity<T extends AbstractDto = AbstractDto> {   

  @PrimaryGeneratedColumn('uuid')
  id: string;

  @CreateDateColumn({
      type: 'timestamp without time zone',
      name: 'created_at',
  })
  createdAt: Date;

  @UpdateDateColumn({
      type: 'timestamp without time zone',
      name: 'updated_at',
  })
  updatedAt: Date;

  @Exclude()
  abstract dtoClass: new (entity: AbstractEntity, options?: any) => T;

  toDto(options?: any) {
      return UtilsService.toDto(this.dtoClass, this, options);
  }

}

User:

@Entity({ name: 'users' })
export class UserEntity extends AbstractEntity<UserDto> {

   @Column({ nullable: true })
   firstName: string;

   @Column({ nullable: true })
   lastName: string;

   @Column({ type: 'enum', enum: RoleType, default: RoleType.USER })
   role: RoleType;

   @Column({ unique: true, nullable: true })
   email: string;

   @Column({ nullable: true })
   password: string;

   @OneToOne(() => ProfileEntity, (profile) => profile.user)
   profile: ProfileEntity;

   @Column({ nullable: true })
    phone: string;

   @Column({ nullable: true })
    avatar: string;

    dtoClass = UserDto;
}

Profile:

@Entity({ name: 'profile' })
export class ProfileEntity {

  @PrimaryGeneratedColumn('uuid')
  id: string;

  @Column({
      type: 'varchar',
      nullable: true,
      length: 100,
  })
  username: string;

  @Column({
      type: 'varchar',
      nullable: true,
      length: 100,
  })
  name: string;

  @OneToOne(() => UserEntity, (user: UserEntity) => user.profile)
  @JoinColumn()
  user: UserEntity;

  @CreateDateColumn({
      type: 'timestamp without time zone',
      name: 'created_at',
  })
  createdAt: Date;
}

I made an override in the createOne function of the Profile Controller to check if the profile already exists by the username field. If the profile exists, the update base function is executed. If not, a new profile is created(Ignore the business logic. It's just for show).

     @Override()
     async createOne(
        @ParsedRequest() req: CrudRequest, 
        @ParsedBody() dto: ProfileRegisterDto
     ) {

      const profile = await this.service.findOne({
          where: { username: dto.username },
      });

      if (profile) {
          return this.base.updateOneBase(req, profile);
      }

      return this.base.createOneBase(req, dto as ProfileEntity);
     }

Project Link: https://github.com/sthormio/nestjsx-crud-issue