I have a query, I'm trying to create a ManyToMany relationship between 2 tables (products and orders) the tables are created fine, but when I want to add the logic in the service to create the records I don't understand how it should be.
This is what I have written till now:
#Entity('pedido')
export class Pedido {
#PrimaryGeneratedColumn()
id: number;
#ManyToMany(() => Product)
#JoinTable({
name: 'pedidos_products',
joinColumn: {
name: 'pedido_id',
},
inverseJoinColumn: {
name: 'product_id',
},
})
product: Product[];
#Column('decimal')
quantity: number;
#Column('decimal')
price: number;
}
#Entity('product')
export class Product {
#PrimaryGeneratedColumn()
id: number;
#Column()
name: string;
#ManyToOne(() => Category, (category) => category.product)
category: Category;
#ManyToMany(() => Pedido)
pedido: Pedido[];
}
Service:
async createPedido(body: any) {
const pedidos = body;
const pedidoInstance = new Pedido();
const productsIds = [];
pedidos.forEach(async (item: any) => {
productsIds.push(item.product_id);
pedidoInstance.price = item.price;
pedidoInstance.quantity = item.quantity;
pedidoInstance.product = productsIds;
await this.pedidoRepository.save(pedidoInstance);
});
return {
ok: true,
};
}
Related
I'm inserting multiple entries simultaneously and wanted to store the child relationships as well, but using the code below, province isn't saving into the database. In essence, I want to save the "province" and user when I save the address, and I receive the userID and provinceID in the request.
entity.ts
#Entity()
export class Address {
#PrimaryGeneratedColumn('uuid')
id: string;
#Column()
address1: string;
#Column({ nullable: true })
address2?: string;
#Column()
country: string;
#ManyToOne(() => Province, (province) => province.addresses, { lazy: true })
#JoinColumn({
name: 'province_id',
})
province: Province;
#ManyToOne(() => User, (user) => user.addresses, {
nullable: false,
onDelete: 'CASCADE',
lazy: true,
})
#JoinColumn({
name: 'user_id',
})
user: User;
}
Request from frontend:
[
{
"address1": "Test 1",
"address2": "Test 1",
"country": "Estonia",
"province_id": "3", // suppose uuid
"user_id": "4" // suppose uuid
},
{
"address1": "Test 2",
"address2": "Test 2",
"country": "Estonia",
"province_id": "3", // suppose uuid
"user_id": "4" // suppose uuid
}
]
service.ts
async saveAddresses (_addresses) {
const addresses: any = _addresses.map((address) => ({
...address,
user: address.user_id,
province: address.province_id
}));
const addressesToCreate = this.addressRepository.create(addresses);
await this.addressRepository.insert(addressesToCreate);
}
As you can see how I'm saving the records but unfortunately, the province and user saving as null and I don't want to query for province again n again.
I tried like this article, and works for me
The code:
//Entity
#Entity('organization')
export class Organization {
#PrimaryGeneratedColumn('uuid')
id: string;
#Column({ type: 'varchar' })
name: string;
#OneToMany(() => Users, (obj) => obj.organization)
users: Users[];
}
#Entity('users')
export class Users {
#PrimaryGeneratedColumn('uuid')
id: string;
#Column({ type: 'varchar' })
name: string;
#ManyToOne(() => Organization, (obj) => obj.users, { cascade: true }) // <--- cascade: true
organization: Organization;
}
//Service
async create(dto: CreateDto[]) {
try {
const orgEntity = function (name: string) {
const org = new Organization();
org.name = name;
return org;
};
const entity: any = dto.map((obj) => ({
...obj,
organization: orgEntity(obj.organization),
}));
const entityCreated = this._repoUser.create(entity);
await this._repoUser.save(entity); // <-- save
return entityCreated;
} catch (err) {
console.log(err);
}
}
//dto
export class CreateDto {
#ApiProperty()
#IsString()
name: string;
#ApiProperty()
#IsString()
organization: string;
}
//request
[
{
"name": "user-1",
"organization":"org-1"
},
{
"name": "user-2",
"organization":"org-2"
}
]
I'm trying to get one record from a nested table.
controller:
#Get(':id/type')
async getType(): Promise<User[]> {
return this.userService.findType();
};
service:
async findType(id: FindOptionsWhere<number>): Promise<User[]> {
return this.userRepository.find({
select: [""], //here I want to select type.type_name
where: {user_id: id}
});
}
entity:
#Entity({ name: 'user' })
export class User {
#PrimaryGeneratedColumn()
public user_id: number;
#OneToOne(() => Type)
#JoinColumn({ name: "type_id", referencedColumnName: "type_id" })
public type: Type;
#Column({ nullable: true, name: 'test_id', type: 'int' })
public test_id: number;
table user:
user_id|type_id|test_id
table type:
type_id|type_name|type_adr
How can I retrieve only type.type_name in the url /:id/type ? thanks
First you have to fix some details, like the param in your route (id). So using your ex.
I'll going to modify the order of the route by convention.
// Controller
#Get('type/:id')
async getType(#Param('id') id: string): Promise<User[]> {
return this.userService.findType();
};
// Service
async findType(id: string): Promise<User[]> {
return this.userRepository.find({
select: { type: true },
where: { user_id: id }
});
}
// And using QueryBuilder
findType(id: string) {
return this.createQueryBuilder('user')
.select(['user.type'])
.where('user.user_id = :id', { id })
.getMany(); // or .getRawMany() to get the raw type
}
When I am trying to update the RFQ it is creating a user automatically using the default value but its nowhere mentioned in the code to create a default new user checked the relations also but couldnot find anything solid
service section
async update(id: number, data: UpdateRfqDto) {
const project = await Rfq.findOne({ where: { id: id } });
if (!project) throw new NotFoundException('Project not found');
const assignee = await this.usersService.findUserById(data.assignee);
if (!assignee) throw new NotFoundException('Assignee not found');
if (data.dueDate) data.dueDate = moment.utc(data.dueDate).format();
if (data.status != 'draft' && !(data.assignee)) throw new NotAcceptableException()
// data.user=assignee
// return data.nonMember;
if (data.nonMember) {
const mem = data.nonMember
const nonmember = (mem.includes(",")) ? mem.split(",") : mem;
this.SendEmailToNonMemberVendor(nonmember, project, data.dueDate);
}
delete data.nonMember;
// return assignee;
// data.user=assignee
this.SendEmailToProjectAssignee(assignee, data.dueDate, project);
let vendorsList = [];
let listVendor = [] ;
if (data.requestVendors.length > 0) {
const vendors=data.requestVendors.map((v)=>{
return v.id;
})
// return vendors;
let vendorsListt = await Users.findBy({ id: In(vendors) });
vendorsList.push(vendorsListt)
await this.SendEmailToRequestQuoteVendor(vendorsListt, data.dueDate, data);
}
delete data.assignee;
delete data.requestVendors;
// return data;
await Rfq.update(id, data);
const newRfq = await Rfq.findOne({
where: { id: id },
relations: ['user'],
});
newRfq.user = assignee;
newRfq.vendors = vendorsList;
await newRfq.save();
return newRfq;
}
async SendEmailToRequestQuoteVendor(vendor, dueDate, project) {
let due = dueDate ? moment(dueDate, 'DD-MM-YYYY') : 'not given';
for (let i = 0; i < vendor.length; i++) {
let emailData = {
name: vendor[i].fullName,
email: vendor[i].email,
subject: VendorRequestTemplate.subject,
body: VendorRequestTemplate.body,
// params:{},
params: {
name: vendor[i].fullName,
dueDate: due,
projectName: project.projectName,
},
};
await sendemail(emailData);
}
//
return vendor;
}
async SendEmailToProjectAssignee(assignee, dueDate, project) {
let due = dueDate ? moment(dueDate, 'DD-MM-YYYY') : 'not given';
let emailData = {
name: assignee.fullName,
email: assignee.email,
subject: AssigneeTemplate.subject,
body: AssigneeTemplate.body,
// params:{},
params: {
name: assignee.fullName,
dueDate: due,
projectName: project.projectName,
},
};
await sendemail(emailData);
return assignee;
}
async SendEmailToNonMemberVendor(vendorEmail, project, dueDate) {
let due = dueDate ? moment(dueDate, 'DD-MM-YYYY') : 'not given';
for (let i = 0; i < vendorEmail.length; i++) {
// if(!inviteSave){
// throw new BadRequestException();
// }
let emailData = {
name: 'Vendor',
email: vendorEmail[i],
subject: InviteVendorTemplate.subject,
body: InviteVendorTemplate.body,
// params:{},
params: {
name: 'Vendor',
dueDate: due,
projectName: project.projectName,
},
};
await sendemail(emailData);
}
return dueDate;
}
model:
import { QuoteMilestone } from 'src/quotePricing/models/quote-milestone.entity';
import { QuotePricing } from 'src/quotePricing/models/quote-pricing.entity';
import {
BaseEntity,
BeforeInsert,
BeforeUpdate,
Column,
CreateDateColumn,
Entity,
JoinColumn,
JoinTable,
ManyToMany,
ManyToOne,
OneToMany,
OneToOne,
PrimaryGeneratedColumn,
UpdateDateColumn,
} from 'typeorm';
import { Users } from '../../users/models/users.entity';
import { InviteVendor } from './invite.entity';
#Entity()
export class Rfq extends BaseEntity {
#PrimaryGeneratedColumn()
id: number;
#Column()
projectName: string;
#Column({ unique: true, default: 'JOB-1' })
jobNumber: string;
#Column()
projectType: string;
#Column({ type: 'text' })
projectDescription: string;
#Column({ type: 'text' })
projectScope: string;
#Column()
attachment: string;
#Column({ default: null })
dueDate: Date;
#Column({ default: 'draft' })
status: string; //draft/created/assigned/quote/paid/completed
#Column()
#CreateDateColumn()
createdAt: Date;
#Column()
#UpdateDateColumn()
updatedAt: Date;
#ManyToOne(() => Users, (user) => user.rfqs) //Assignee
user: Users;
#ManyToOne(() => Users, (user) => user.created_by) //CreatedBy
created_by: Users;
#OneToMany(() => QuotePricing, (QuotePricing) => QuotePricing.rfq)
quotePricings: QuotePricing[];
#OneToMany(() => InviteVendor, (invite) => invite.project)
inviteVendor: InviteVendor[];
#OneToMany(() => QuoteMilestone, (milestone) => milestone.rfq)
milestone: QuoteMilestone[];
#ManyToMany(() => Users, (requestVendors: Users) => requestVendors.id, {
cascade: true,
})
#JoinTable({
name: 'rfqs_vendors',
joinColumn: {
name: 'rfqId',
referencedColumnName: 'id',
},
inverseJoinColumn: {
name: 'userId',
referencedColumnName: 'id',
},
})
vendors: Users[];
}
I have tried in many ways but not able to find any way out please help
and any help would be highly appriciated
product.entity.ts
#Entity()
export class Product extends CoreEntity {
#Field(type => String)
#PrimaryColumn('varchar2', { name: 'BAR_CODE' })
barcode: string;
#Field(type => String, { nullable: true })
#Column('varchar2', { name: 'GOODS_NAME', nullable: true })
goodsName: string | null;
#Field(type => Number, { nullable: true })
#Column('number', { name: 'SALE_PRICE', nullable: true, precision: 12, scale: 0 })
salePrice: number | null;
#Field(type => [PromotionProduct])
#OneToMany(
type => PromotionProduct,
promotionProduct => promotionProduct.product,
)
promotionProducts: PromotionProduct[];
}
promotion.entity.ts
#Entity()
export class Promotion extends CoreEntity {
#Field(type => String)
#PrimaryColumn('varchar2', { name: 'PROMOTION_CODE' })
promotionCode: string;
#Field(type => String)
#Column('varchar2', { name: 'PROMOTION_NAME' })
promotionName: string;
#Field(type => String)
#Column('varchar2', { name: 'PROMOTIONSTART_DAY' })
promotionStartDay: string;
#Field(type => String)
#Column('varchar2', { name: 'PROMOTIONEND_DAY' })
promotionEndDay: string;
#Field(type => [PromotionProduct], { nullable: true })
#OneToMany(
type => PromotionProduct,
promotionProduct => promotionProduct.promotion,
)
promotionProducts: PromotionProduct[];
}
promotionProduct.entity.ts
#Entity()
export class PromotionProduct extends CoreEntity {
#Field(type => String)
#PrimaryColumn('varchar2', { name: 'PROMOTION_CODE' })
promotionCode: string;
#Field(type => String)
#PrimaryColumn('varchar2', { name: 'BAR_CODE' })
barcode: string;
#Field(type => Number, { nullable: true })
#Column('number', { name: 'DC_SALE_PRICE' })
dcSalePrice: number | null;
#Field(type => Promotion, { nullable: true })
#JoinColumn({ name: 'PROMOTION_CODE' })
#ManyToOne(
type => Promotion,
promotion => promotion.promotionProducts,
{ nullable: true, onDelete: 'SET NULL' },
)
promotion: Promotion;
#Field(type => Product)
#JoinColumn({ name: 'BAR_CODE' })
#ManyToOne(
type => Product,
product => product.promotionProducts,
)
product: Product;
}
Promotion has many PromotionProduct (1:N)
Product has many PromotionProduct (1:N)
Example,
Product A is promotion target.
Product B is not promotion target.
So Product A has promotionProduct dcSalePrice
Product B hasn't promotionProduct dcSalePrice, just product salePrice.
I want all products with promotion, regardless of whether it's for the promotion or not.
And, PromotionStartDay is LessThanEqual Today, PromotionEndDay is MoreThanEqual.
products.service.ts
const productRepository = await connection.getRepository(Product);
const results = await productRepository.find(
{
relations: ['promotionProducts', 'promotionProducts.promotion'],
where: {
promotionProducts: {
promotion: {
promotionStartDay: LessThanOrEqual(currentDate),
promotionEndDay: MoreThanOrEqual(currentDate),
}
}
}
}
);
But it occurs an error like this:
Cannot query across one-to-many for property promotionProducts
I guess it's like the promotionProducts property doesn't have promotion, but promotionProducts relationship has promotion properties.
I'm not used to typeORM yet, so if you know it, please help me.
I have this two entities:
#Entity()
export class Member {
#PrimaryColumn({ name: 'room_id' })
roomId: number;
#PrimaryColumn()
email: string;
#Column({ name: 'is_room_owner' })
isRoomOwner: boolean;
#Column('timestamp without time zone', { name: 'joined_at', nullable: true })
joinedAt: Date | null;
#CreateDateColumn({ name: 'created_at' })
createdAt: Date;
#ManyToOne(() => Room, room => room.members)
#JoinColumn({ name: 'room_id' })
room: Room;
}
#Entity()
export class Room {
#PrimaryGeneratedColumn({ name: 'room_id' })
roomId: number;
#Column()
name!: string;
#Column()
permanent!: boolean;
#Column()
active!: boolean;
#CreateDateColumn({ name: 'created_at' })
createdAt: Date;
#UpdateDateColumn({ name: 'updated_at' })
updatedAt: Date;
#OneToMany(() => Member, member => member.room, { cascade: true })
members: Member[];
}
I would like to get the rooms by the member's email and filter if they are active.
Basically in sql it would be something like this:
select "room".*, "member".* from room "room"
inner join member "member" on "member".roomId = "room".roomId
where "room".active = :active and "member".email = :email;
It should include the members.
I am getting used to typeorm so thanks a lot for any help!
The query can be constructed using query builder as follows -
async getRoomsByMember(active: boolean, email: string): Promise<any[]> {
return await getRepository(Room)
.createQueryBuilder('room')
.innerJoinAndSelect('room.member', 'member')
.where("room.active = :active", {active: active})
.andWhere("member.email = :email", { email: email })
.getMany();
}