Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issues creating a new product with a variant with money amount #5306

Closed
ConnysCode opened this issue Oct 6, 2023 · 4 comments · Fixed by #5410
Closed

Issues creating a new product with a variant with money amount #5306

ConnysCode opened this issue Oct 6, 2023 · 4 comments · Fixed by #5410

Comments

@ConnysCode
Copy link

Bug report

Hi there,

It's been a while since we last reached out. I hope you're all doing well.

I'm writing to you today because we've encountered an issue with inserting new products in Medusa, and I could use some assistance in resolving it.

When attempting to create a new product, even with the most basic data, we've noticed that Medusa is not correctly handling the money amount. I want to clarify that I may be missing something obvious, but here's a simplified version of how we're trying to create a product:

await this.productService_.create(
  {
    ...productPayload, variants: [
      {
        title: "Default",
        sku: product.SUPPLIER_PID._text,
        prices: [{ amount: 1, currency_code: "eur" }],
        inventory_quantity: 100,
      },
    ]
  }
);

However, it seems that the insert query is not capturing the money amount correctly. Here's the relevant error message we're encountering:

{
    "query": "INSERT INTO \"public\".\"product_variant_money_amount\"(\"variant_id\", \"money_amount_id\") VALUES ($1, DEFAULT)",
    "parameters": [
        "variant_01HC2VRNTCZTASV9EPJ0BM3NCW"
    ],
    "driverError": {
        "length": 342,
        "name": "error",
        "severity": "ERROR",
        "code": "23502",
        "detail": "Failing row contains (null, null, variant_01HC2VRNTCZTASV9EPJ0BM3NCW, null, 2023-10-06 16:05:10.897964+00, 2023-10-06 16:05:10.897964+00).",
        "schema": "public",
        "table": "product_variant_money_amount",
        "column": "id",
        "file": "execMain.c",
        "line": "1883",
        "routine": "ExecConstraints"
    },
    "length": 342,
    "severity": "ERROR",
    "code": "23502",
    "detail": "Failing row contains (null, null, variant_01HC2VRNTCZTASV9EPJ0BM3NCW, null, 2023-10-06 16:05:10.897964+00, 2023-10-06 16:05:10.897964+00).",
    "schema": "public",
    "table": "product_variant_money_amount",
    "column": "id",
    "file": "execMain.c",
    "line": "1883",
    "routine": "ExecConstraints"
}

From what I understand, it appears that Medusa is trying to create a new relation with a default value for the money amount, when it should be set to 1 in this particular case.

Thank you very much for your help! ❤️


System information

Medusa version: v17.0.0
Node.js version: v20.5.1
Database: Postgresql
Operating system: MacOS 14.0

@olivermrbl
Copy link
Contributor

@ConnysCode – thanks for filing this issue. If you want to interface directly with our services instead of our Rest API, you'll need to create variants and their prices subsequent to creating the product. You can see the flow of events in the POST /admin/products handler.

product = await entityManager.transaction(async (manager) => {
const { variants } = validated
delete validated.variants
if (!validated.thumbnail && validated.images && validated.images.length) {
validated.thumbnail = validated.images[0]
}
let shippingProfile
// Get default shipping profile
if (validated.is_giftcard) {
shippingProfile = await shippingProfileService
.withTransaction(manager)
.retrieveGiftCardDefault()
} else {
shippingProfile = await shippingProfileService
.withTransaction(manager)
.retrieveDefault()
}
// Provided that the feature flag is enabled and
// no sales channels are available, set the default one
if (
featureFlagRouter.isFeatureEnabled(SalesChannelFeatureFlag.key) &&
!validated?.sales_channels?.length
) {
const defaultSalesChannel = await salesChannelService
.withTransaction(manager)
.retrieveDefault()
validated.sales_channels = [defaultSalesChannel]
}
const newProduct = await productService
.withTransaction(manager)
.create({ ...validated, profile_id: shippingProfile.id })
if (variants) {
for (const [index, variant] of variants.entries()) {
variant["variant_rank"] = index
}
const optionIds =
validated?.options?.map(
(o) => newProduct.options.find((newO) => newO.title === o.title)?.id
) || []
const allVariantTransactions: DistributedTransaction[] = []
const transactionDependencies = {
manager,
inventoryService,
productVariantInventoryService,
productVariantService,
}
try {
const variantsInputData = variants.map((variant) => {
const options =
variant?.options?.map((option, index) => ({
...option,
option_id: optionIds[index],
})) || []
return {
...variant,
options,
} as CreateProductVariantInput
})
const varTransaction = await createVariantsTransaction(
transactionDependencies,
newProduct.id,
variantsInputData
)
allVariantTransactions.push(varTransaction)
} catch (e) {
await Promise.all(
allVariantTransactions.map(async (transaction) => {
await revertVariantTransaction(
transactionDependencies,
transaction
).catch(() => logger.warn("Transaction couldn't be reverted."))
})
)
throw e
}
}

@ConnysCode
Copy link
Author

Hey @olivermrbl
Thank you for your response. I've noticed this behavior in the core route, but it seems like something has changed recently. I however couldn't find any information about breaking changes related to this in the upgrade guides.

We've been using this method to import products in our production service for several months, and it has just now suddenly stopped working (we did not even upgrade recently). Are you certain that it's not possible to create them in this way? If that's the case, could you please explain why Medusa doesn't catch this and omits the variants value when creating a new product? This seems especially puzzling because when updating a product, you can't include a variant as well. So, I don't see the point of including them in the creation interface.

@olivermrbl
Copy link
Contributor

I might have found the culprit. In v1.16.0, we updated the relationship between money amounts (prices) and product variants from a many-to-one to a many-to-many. This was a breaking change.

Can you check if the migration from this release has been run against your database?

Try to run:

SELECT * FROM "migrations";

The change has been applied if you see a migration named dropMoneyAmountConstraintsForPricingModule1692953518123.

Creating variants and prices directly using the ProductService is not supported in versions after 1.16.0.

I'll forward this to our team to see if we can add back the support for the updated schema. Until then, you'll have to use a combination of services to achieve this. You can use the handler I linked to in a previous message as source of inspiration.

@ConnysCode
Copy link
Author

@olivermrbl Thanks for the info! Seeing this feature again would be amazing.

It would've been nice, to see that breaking change in the upgrade info tho ^^
https://docs.medusajs.com/upgrade-guides/medusa-core/1-17-0#overview

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants