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

[Bug]: Custom LineItem is dependent on a Product Variants #10099

Closed
AlexAntonides opened this issue Nov 14, 2024 · 8 comments
Closed

[Bug]: Custom LineItem is dependent on a Product Variants #10099

AlexAntonides opened this issue Nov 14, 2024 · 8 comments

Comments

@AlexAntonides
Copy link

Package.json file

{
    [...]
    "scripts": { [...] },
    "dependencies": {
        "@medusajs/admin-sdk": "latest",
        "@medusajs/framework": "latest",
        "@medusajs/medusa": "latest",
        "@medusajs/cli": "latest",
        "@mikro-orm/core": "5.9.7",
        "@mikro-orm/knex": "5.9.7",
        "@mikro-orm/migrations": "5.9.7",
        "@mikro-orm/postgresql": "5.9.7",
        "awilix": "^8.0.1",
        "pg": "^8.13.0",
        [...]
    },
    "devDependencies": {
        "@mikro-orm/cli": "5.9.7",
        "@medusajs/test-utils": "latest",
        [...]
    }
}

Node.js version

v20.17.0

Database and its version

PostgreSQL v10.4

Operating system name and version

macOS Sequoia 15.1

Browser name

No response

What happended?

I've been working on a Subscription module, with custom subscription models, rather than extending the product/variant entities with additional_data. However, I'd like to be able to attach these custom models to a LineItem of a cart/order, but I'm having a hard time to implement this.

Similarly to how products/variants are linked to orders, my idea was to extend the OrderLineItem model to add the properties { subscription_id, subscription_title, [...], } to additional_data.

My hope for this is that I would be able to create a LineItem { title: subscription.title, [...] } and add the subscription data to the additional_data { subscription_title: subscription.title, [...] } (which is how products/variants are linked to LineItems).

However, while testing, I've noticed that LineItems are somewhat dependent on products/variants, rather than being standalone as promised.

When I create a DraftOrder through the API (POST /admin/draft-orders) with the following data,

{
     [...],
     "items": [
           {
                  "title": "Subscription", 
                  "quantity": 1,
                  "unit_price": [...],
           }
     ],
     [...]
}

I receive the error,

{
       "type": "invalid_data",
       "message": "Invalid request: Invalid input"
}

Later on I figured out that this was because the sku property is required, even though both the validator and the DTO define the property as optional.

But I also noticed that in the Order workflow, in the case of a "custom line item", the variant is attached and the variant_sku/variant_title properties are placed using the given item (variant_title: item.title).

This gives me the feeling that the LineItem of the Order Module is not truly decoupled from the rest of the modules, because it still tries to link itself to a products/variants from the Product Module.

While I could try to make this work by adding a hack like adding a SKU to my subscription (which I don't want), or to set the SKU to a random value or to ignore all "variant_titles", it feels like it's better to not set the variant_title/variant_sku/variant_barcode on a custom line item, because according to the DTO, these properties are optional anyway.

Expected behavior

I expect the variant_title/variant_sku/variant_barcode properties on the OrderLineItem to be optional, considering both the DTO and Validator says it is.

So, when I POST /admin/draft-orders) with body,

{
     [...],
     "items": [
           {
                  "title": "Subscription", 
                  "quantity": 1,
                  "unit_price": [...],
           }
     ],
     [...]
}

I expect a Custom LineItem to be created with,

{
     "title": "Subscription",
     "variant_title": undefined,
     "variant_sku": undefined,
     [...]
} 

Actual behavior

POST /admin/draft-orders) with body,

{
     [...],
     "items": [
           {
                  "title": "Subscription", 
                  "quantity": 1,
                  "unit_price": [...],
           }
     ],
     [...]
}

Returns

{
       "type": "invalid_data",
       "message": "Invalid request: Invalid input"
}

POST /admin/draft-orders) with body,

{
     [...],
     "items": [
           {
                  "title": "Subscription", 
                  "sku": "random_value",
                  "quantity": 1,
                  "unit_price": [...],
           }
     ],
     [...]
}

returns

{
     "title": "Subscription",
     "variant_title": "Subscription",
     "variant_sku": "random_value",
     [...]
} 

Link to reproduction repo

@olivermrbl
Copy link
Contributor

@AlexAntonides, any chance you can share what you have now in a repository? I think it would help in understanding what you are trying to achieve.

Two things I'll say:

  • Our admin dashboard currently does not support draft orders, so to manage these, you would have to build some extensions. Draft orders is on the roadmap, and we hope to introduce it early next year.
  • Our cart and order flows are not yet fully compatible with custom line items, so you will likely find minor issues, like the one you highlighted with the variant <> order line item association. Custom line items is also on our roadmap, and you can expect it sometime before mid-December.

Finally, have you read our Subscription Recipe? It might be helpful, although it seems the use case is slightly different.

@olivermrbl olivermrbl self-assigned this Nov 15, 2024
@AlexAntonides
Copy link
Author

Hi @olivermrbl, thank you for the response.

Unfortunately, I am not able to share the code due to company policy, however, I'll try to explain the intent as clear as possible with code snippets.

First things first, we don't use the admin dashboard. We use our own front-end application that uses the Medusa backend, hence the reason why we do use draft orders on our side.

Second, I'm glad that custom line items are on the roadmap, as this is necessary for us to support custom order-able items that are not typical products and/or variants. For example, we've tried to create a module that supports the creation of bundles (an item that allows us to create discount packages/personalized boxes that consists of products/variants and subscriptions), and as described earlier, the subscription services.

We've checked the subscription recipe earlier and while it's useful, it doesn't support our use case, considering the recipe is more centred around implementing a recurring order (repeating the same order in an interval), rather than offering specific subscriptions products, such as cloud services, that can be bought alongside other products/variants.

We've also thought about extending the product, however, this doesn't support our use case either, considering we need a more detailed subscription services that separates the billing from entitlement architecture, with tiers, various plans and different add-on packages. This is significantly different than the products/variants approach, and extending these entities would result in a bunch of dirty hacks to support our goals (i.e. the subscription/tier/plan layers, and some minor details, for example, a subscription doesn't have a SKU (which is mandatory for a variant)).

So, our goal for now has been to create a module with this entire architecture, with the intend to extend the LineItem to support the order of these custom entities, considering the LineItems are fairly decoupled from the products/variants (LineItems do not require/do not depend on these entities), through the use of custom line items (Which only requires a title and some unit pricing details, according to the DTO) (except for the part that I described above, with the line that sets the variant_title to the input_title, and which makes the variant_sku mandatory).

We've seen in the DTO, that the products and variants are "attached" to these line items by adding the optional properties (product_id, product_title, product_etc, variant_id, variant_title, variant_etc), so our plan was to replicate the same logic with our bundles and subscriptions, by extending the LineItem with

export interface OrderLineItemDTO extends OrderLineItemTotalsDTO {
      [...]
      title: string,
      product_id?: string,
      product_title?: string,
      variant_id?: string,
      variant_title?: string,       // This time, undefined, when no variant data is supplied
      variant_sku?: string,         // This time, optional, rather than ""optional"" (secretly required)
      [...]
      additional_data?: {
            subscription_id?: string,
            subscription_title?: string,
            [...]
            tier_id?: string,
            tier_title?: string,
            [...]
            plan_id?: string,
            [...]
            bundle_id?: string,
            bundle_title?: string,
      }
      [...]
}

With the thought that the LineItems would still work (because the required title, and pricing properties are supplied), while being able to distinguish the type of the LineItem by checking whether the property (variant_id, subscription_id, etc.) exists.

While we can wait for Medusa to support the extension of these custom line items, the requirement of variant data (sku/barcode) and setting the variant_title: input.title is standing in our way, because it adds a dependency to these items (now we need to fill in a sku/barcode for a subscription, which it doesn't have, and we'd rather not hack our way by supplying sku/barcode with the string "UNUSED"), making it harder for us to tell whether a custom line item is a variant or one of these custom entities.

As to our understand, the Order and Product modules should be decoupled, while behind it, it seems like the variant data is still required in a way.
This is why we'd like it if these dependencies are removed, like the OrderLineItemDTO describes.

@olivermrbl
Copy link
Contributor

@AlexAntonides, thanks for sharing your use case in detail. It helps a lot.

I am currently scoping out the support for custom line items, and I have a few questions about your subscription and bundle use cases.

Any chance we could jump on a call? If so, how can I reach you? We can summarise our conversation in the issue here afterward for transparency for the community.

@AlexAntonides
Copy link
Author

@olivermrbl, thank you for your response and interest in my use case. I'm happy to provide more details. I think the best way to reach me is through the Medusa Discord Community. My server nickname is "AlexAntonides"!

@olivermrbl
Copy link
Contributor

@AlexAntonides, I couldn't find you on Discord. Can you ping me in private DMs?

@AlexAntonides
Copy link
Author

Any news on this?

Copy link
Contributor

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 3 days.

@github-actions github-actions bot added the Stale label Jan 18, 2025
Copy link
Contributor

This issue was closed because it has been stalled for 3 days with no activity.

@github-actions github-actions bot closed this as not planned Won't fix, can't repro, duplicate, stale Jan 25, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants