I'm trying to save a Product that has many Categories. At the same time a Category can have many Products. So I think the best solution is a ManyToMany relationship to model my data.
When I try to create a new product, an error ocurred saying that it isn't possible insert a new Category with null values. The crazy thing is that I don't need to create new categories, instead that I want to take the existing ones and assign them to the new product.
This is the SQL message that console returns:
SQLITE_CONSTRAINT: NOT NULL constraint failed: category.name',
errno: 19,
code: 'SQLITE_CONSTRAINT',
name: 'QueryFailedError',
query: 'INSERT INTO "category"("id", "parent_id", "name", "description", "createdAt", "updatedAt") VALUES (NULL, NULL, NULL, NULL, datetime(\'now\'), datetime(\'now\'))
Following the typeorm documentation example I deduce that my code must be something like next:
Product.ts
@Entity()
@Unique(["code"])
export class Product {
@PrimaryGeneratedColumn()
id: number;
@Column({
length: 20
})
code: string;
@Column({
length: 100
})
name: string;
@Column()
description: string;
@Column()
stock: number;
@Column({
type: "real"
})
price: number;
@Column()
public_price: boolean;
@Column()
public: boolean;
@ManyToMany(type => Category, category => category.products, {
cascade: true
})
@JoinTable()
categories: Category[];
}
Category.ts
@Entity()
export class Category {
@PrimaryGeneratedColumn()
id: number;
@Column({ nullable: true })
parent_id: number;
@Column()
@IsNotEmpty()
name: string;
@Column()
description?: string;
@Column()
@CreateDateColumn()
createdAt: Date;
@Column()
@UpdateDateColumn()
updatedAt: Date;
@ManyToMany(type => Product, product => product.categories)
products: Product[];
}
ProductController.ts (create method)
static create = async (req: Request, res: Response) => {
const { categories, ...data } = req.body
const categoryRepository = getRepository(Category);
const productRepository = getRepository(Product);
const cats = []
for (const id of categories) {
const cat = await categoryRepository.find(id)
cats.push(cat)
}
const product = new Product();
for (const index in data) {
product[index] = data[index]
}
product.categories = cats
try {
await productRepository.save(product);
res.send('Product successfuly created');
} catch (err) {
console.log(err)
res.status(409).send('Error on product creation');
}
}
And this is the JSON object that I'm using to test my application through Postman:
{
"code": "1234",
"name": "TESTING PRODUCT CREATION",
"description": "Product sended through postman",
"stock": "99",
"price": "255.88",
"public_price": true,
"public": true,
"categories": [1]
}
Replace
await categoryRepository.find(id)
with
await categoryRepository.findOne(id)
find
will return the item in Array
.