I am trying to seed my prisma db but am having trouble doing so with a user -> Payment relation.
Seeder Code:
export const userSeeder = async (prisma) => {
const productIds = await getProductIds(prisma);
const {
gamingLaptopProductId,
chairProductId,
cologneProductId,
} = productIds;
console.log(chalk.blue('ABOUT TO RUN BOBBYS SEEDER'));
const bobby = await prisma.user.upsert({
where: { email: '[email protected]' },
update: {},
create: {
username: 'bobby',
email: '[email protected]',
password: 'bob123',
first_name: 'Bob',
last_name: 'Brown',
role: 'ADMIN',
created_at: new Date().toISOString(),
updated_at: new Date().toISOString(),
deleted: false,
UserAddress: {
create: [
{
address_type: 'Shipping',
address: {
create: {
address_type: 'Shipping',
street_address: '123 Fake Street',
city: 'New York',
state: 'NY',
zip_code: '12345',
country: 'USA',
created_at: new Date().toISOString(),
updated_at: new Date().toISOString(),
deleted: false,
},
},
created_at: new Date().toISOString(),
updated_at: new Date().toISOString(),
deleted: false,
},
{
address_type: 'Billing',
address: {
create: {
address_type: 'Billing',
street_address: '742 Evergreen Terrace',
city: 'Springfield',
state: 'OR',
zip_code: '99898',
country: 'USA',
created_at: new Date().toISOString(),
updated_at: new Date().toISOString(),
deleted: false,
},
},
created_at: new Date().toISOString(),
updated_at: new Date().toISOString(),
deleted: false,
},
],
},
comments: {
create: [
{
product_id: gamingLaptopProductId,
content: 'This is a great Laptop!',
created_at: new Date().toISOString(),
updated_at: new Date().toISOString(),
deleted: false,
},
{
product_id: tshirtProductId,
content: 'Such a nice shirt',
created_at: new Date().toISOString(),
updated_at: new Date().toISOString(),
deleted: false,
},
],
},
ratings: {
create: [
{
product_id: cologneProductId,
rating: 5,
created_at: new Date().toISOString(),
updated_at: new Date().toISOString(),
deleted: false,
},
{
product_id: tshirtProductId,
rating: 3,
created_at: new Date().toISOString(),
updated_at: new Date().toISOString(),
deleted: false,
},
],
},
},
});
if (bobby) {
console.log(chalk.green('Bobby was created successfully.'));
await prisma.payment.create({
data: {
user: bobby,
payment_method: 'Credit Card',
exp_month: 0o1,
exp_year: 2026,
card_number: '1233-4567-8901-2292',
payment_status: 'PENDING',
created_at: new Date().toISOString(),
updated_at: new Date().toISOString(),
deleted: false,
Order: {
create: [
{
status: 'Shipped',
total_price: 41.5,
created_at: new Date().toISOString(),
updated_at: new Date().toISOString(),
deleted: false,
OrderItem: {
create: [
{
product_id: chairProductId,
quantity: 1,
price: 35.99,
created_at: new Date().toISOString(),
updated_at: new Date().toISOString(),
deleted: false,
},
],
},
},
],
},
},
});
console.log(chalk.green('Payment was created successfully.'));
} else {
console.error(chalk.red('Bobby was not found.'));
}
console.log('[Users w/ Addresses, Orders, Reviews, and Comments seeded successfully]');
};
Relevant Prisma Models:
model User {
id String @id @default(uuid())
username String @unique
email String @unique
password String
first_name String
last_name String?
created_at DateTime @default(now())
updated_at DateTime @updatedAt
deleted Boolean @default(false)
role String @default("USER")
comments Comment[]
ratings Rating[]
orders Order[]
UserAddress UserAddress[]
payments Payment[]
}
model Payment {
id String @id @default(uuid())
user User @relation(fields: [user_id], references: [id])
user_id String // Change type to String
payment_method String // Mock payment method (e.g., "credit card")
exp_month Int? // Optional, month of expiration (e.g., 1 for January)
exp_year Int? // Optional, year of expiration (e.g., 2024)
card_number String? // Optional, masked card number (e.g., "XXXX XXXX XXXX XXXX")
payment_status String @default("PROCESSED") // Mock payment status (e.g., "success", "failure")
created_at DateTime @default(now())
updated_at DateTime @updatedAt
deleted Boolean @default(false)
Order Order[]
}
model Order {
id String @id @default(uuid())
user User @relation(fields: [user_id], references: [id])
user_id String
status String
total_price Float
payment Payment @relation(fields: [payment_id], references: [id])
payment_id String
created_at DateTime @default(now())
updated_at DateTime @updatedAt
deleted Boolean @default(false)
OrderItem OrderItem[]
}
model OrderItem {
id String @id @default(uuid())
order Order @relation(fields: [order_id], references: [id])
order_id String // Field will exist in db
product Product @relation(fields: [product_id], references: [id])
product_id String // Field will exist in db
quantity Int
price Float
created_at DateTime @default(now())
updated_at DateTime @updatedAt
deleted Boolean @default(false)
}
All other relations (comments, ratings etc…) all get created properly, I am only having trouble with the payments
creation on the user.
If I run npx prisma migrate reset
this is the error I get:
ABOUT TO RUN BOBBYS SEEDER
Bobby was created successfully.
PrismaClientValidationError:
Invalid `prisma.payment.create()` invocation:
{
data: {
user: {
id: "81e533bf-dc27-4b1f-89a1-44384dfa13b1",
~~
username: "bobby",
email: "[email protected]",
password: "bob123",
first_name: "Bob",
last_name: "Brown",
created_at: new Date("2024-05-06T14:35:34.112Z"),
updated_at: new Date("2024-05-06T14:35:34.112Z"),
deleted: false,
role: "ADMIN",
? create?: UserCreateWithoutPaymentsInput | UserUncheckedCreateWithoutPaymentsInput,
? connectOrCreate?: UserCreateOrConnectWithoutPaymentsInput,
? connect?: UserWhereUniqueInput
},
payment_method: "Credit Card",
exp_month: 1,
exp_year: 2026,
card_number: "1233-4567-8901-2292",
payment_status: "PENDING",
created_at: "2024-05-06T14:35:34.117Z",
updated_at: "2024-05-06T14:35:34.117Z",
deleted: false,
Order: {
create: [
{
status: "Shipped",
total_price: 41.5,
created_at: "2024-05-06T14:35:34.117Z",
updated_at: "2024-05-06T14:35:34.117Z",
deleted: false,
OrderItem: {
create: [
{
product_id: "581b8e88-080f-4d04-a55d-9db52d4be97a",
quantity: 1,
price: 35.99,
created_at: "2024-05-06T14:35:34.117Z",
updated_at: "2024-05-06T14:35:34.117Z",
deleted: false
}
]
}
}
]
}
}
}
Unknown argument `id`. Available options are marked with ?.
This is the error I get when replacing the user
object with just the user_id
:
ABOUT TO RUN BOBBYS SEEDER
Bobby was created successfully.
PrismaClientValidationError:
Invalid `prisma.payment.create()` invocation:
{
data: {
user_id: "33891012-2c5a-4e8c-91e9-29007c29172b",
payment_method: "Credit Card",
exp_month: 1,
exp_year: 2026,
card_number: "1233-4567-8901-2292",
payment_status: "PENDING",
created_at: "2024-05-06T14:55:47.335Z",
updated_at: "2024-05-06T14:55:47.335Z",
deleted: false,
Order: {
create: [
{
status: "Shipped",
total_price: 41.5,
created_at: "2024-05-06T14:55:47.335Z",
updated_at: "2024-05-06T14:55:47.335Z",
deleted: false,
OrderItem: {
create: [
{
product_id: "89fbc564-1af8-494e-84c6-5e1f446f3e59",
quantity: 1,
price: 35.99,
created_at: "2024-05-06T14:55:47.335Z",
updated_at: "2024-05-06T14:55:47.335Z",
deleted: false
}
]
}
}
]
}
}
}
Argument `user` is missing.
So naturally I tried removing the id
before the create but then it throws the same error about username, then email and so on…if I try to just pass user_id
it says missing property user
…which is why I am passing the entire bobby user.
I am not sure how to make this work…any ideas would help. Thanks!
2
Answers
You need to replace the
user
object with just theuser_id
.A simple solution
What you should be doing is connecting the new payment to an existing user. The concept you are looking for is
connect
(documentation).A better solution
Create the user and payment in statement. This is safer as both either succeed or fail together – I know we are talking about merely seeding the DB, but this is a good pattern to use to improve data integrity. This also has the benefit of not having to 1) use explicit transactions and 2) not having to write
if X succeeds then create Y
.With that in mind, I would write your create statement as:
Further hints
You can omit all the timestamp fields as according to schema, they default to the current moment. This makes your code easier to read.
To elaborate on the previous point: trust the schema defaults. There is no need to explicitly set a field’s value if you wish to use the default. Again: easier to read, easier to make changes in the future.
Take a look at Prisma’s naming conventions. Sticking to those (e.g. not using
snake_case
butPascalCase
) makes your code easier for other developers familiar with Prisma easier, more logical to follow.