I have a Lambda function with a Postgres DB, where I am using Prisma to upsert a parent charge object with multiple charge_item children. At first, I initially tried to upsert the charge first and then upsert the charge_items, but on doing so I kept getting the error:
Foreign key constraint failed on the field:
charge_items_charge_id_fkey (index)
I changed my approach to upserting the children first then the parent, but still, I am seeing the same error.
Here is the models:
model charges {
id Int @id @default(autoincrement())
charge_id BigInt @unique
address_id BigInt
customer_id BigInt
order_id BigInt?
subscription_ids Json @default("[]")
charge_items charge_items[]
created_at DateTime @default(now())
updated_at DateTime @default(now())
}
model charge_items {
id Int @id @default(autoincrement())
charge_id BigInt
subscription_id BigInt @unique
product_id BigInt
variant_id BigInt
purchase_item_type String
quantity Int
total_price String
unit_price String
product products @relation(fields: [product_id], references: [product_id], onDelete: Cascade, onUpdate: Cascade)
variant variants @relation(fields: [variant_id], references: [variant_id], onDelete: Cascade, onUpdate: Cascade)
subscription subscriptions @relation(fields: [subscription_id], references: [subscription_id], onDelete: Cascade, onUpdate: Cascade)
charge charges @relation(fields: [charge_id], references: [charge_id], onDelete: Cascade, onUpdate: Cascade)
created_at DateTime @default(now())
updated_at DateTime @default(now())
}
And here is the current logic:
items.forEach(async (item) => {
await prisma.charge_items.upsert({
where: {
subscription_id: item.purchase_item_id
},
update: {
purchase_item_type: item.purchase_item_type,
quantity: item.quantity,
total_price: item.total_price,
unit_price: item.unit_price,
updated_at: item.updated_at
},
create: {
charge_id: charge.id,
subscription_id: item.purchase_item_id,
product_id: parseInt(item.external_product_id.ecommerce),
variant_id: parseInt(item.external_variant_id.ecommerce),
purchase_item_type: item.purchase_item_type,
quantity: item.quantity,
total_price: item.total_price,
unit_price: item.unit_price,
charge: {
create: {
charge_id: charge.id,
address_id: charge.address_id,
customer_id: charge.customer?.external_customer_id?.ecommerce
? parseInt(charge.customer?.external_customer_id?.ecommerce)
: undefined,
order_id: charge.external_order_id.ecommerce
? parseInt(charge.external_order_id.ecommerce)
: undefined,
subscription_ids: items.map((x) => {
return x.purchase_item_id
}),
updated_at: charge.updated_at,
created_at: charge.created_at
}
},
created_at: charge.created_at,
updated_at: charge.updated_at
}
})
})
await prisma.charges.upsert({
where: {
charge_id: charge.id
},
update: {
order_id: charge.external_order_id.ecommerce
? parseInt(charge.external_order_id.ecommerce)
: undefined,
subscription_ids: items.map((x) => {
return x.purchase_item_id
}),
updated_at: charge.updated_at
},
create: {
charge_id: charge.id,
address_id: charge.address_id,
customer_id: charge.customer?.external_customer_id?.ecommerce
? parseInt(charge.customer?.external_customer_id?.ecommerce)
: undefined,
order_id: charge.external_order_id.ecommerce
? parseInt(charge.external_order_id.ecommerce)
: undefined,
subscription_ids: items.map((x) => {
return x.purchase_item_id
}),
updated_at: charge.updated_at,
created_at: charge.created_at
}
})
My question is, how can I safely create or update both the parent and child row(s) and prevent this restraint from failing in the future? I've seen documentation on implementing createOrConnect, but only in the .create() function, not upserts. Would createOrConnect still work for upserts? Or is there a better approach?