skip to Main Content

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


  1. You need to replace the user object with just the user_id.

    if (bobby) {
        console.log(chalk.green('Bobby was created successfully.'));
    
        
        await prisma.payment.create({
          data: {
            user_id: bobby.id, // Use only the user's ID
            payment_method: 'Credit Card',
            exp_month: 1,
            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.'));
    }
    
    Login or Signup to reply.
  2. 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).

    await prisma.payment.create({
      data: {
        user: {
          connect: {
            id: bobby.id,
          },
        },
        payment_method: 'Credit Card',
        // the rest of the properties...
      },
    });
    
    

    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:

    const bobby = await prisma.user.upsert({
      where: { email: '[email protected]' },
      update: {},
      create: {
        username: 'bobby',
        email: '[email protected]',
        // snip snip...
        role: 'ADMIN',
        // We can omit 'created_at' as it defaults to now()
        // created_at: new Date().toISOString(),
        updated_at: new Date().toISOString(),
        // This can be omitted, too...
        // deleted: false,
        payments: {
          // Create a new payment and automatically
          // connect it to the user being created
          create: [
            {
              payment_method: 'Credit Card',
              exp_month: 0o1,
              exp_year: 2026,
              // snip snip...
            },
          ],
        },
      },
    });
    
    

    Further hints

    1. You can omit all the timestamp fields as according to schema, they default to the current moment. This makes your code easier to read.

    2. 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.

    3. Take a look at Prisma’s naming conventions. Sticking to those (e.g. not using snake_case but PascalCase) makes your code easier for other developers familiar with Prisma easier, more logical to follow.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search