Closed bkvaiude closed 1 year ago
Thank you for submitting this issue! Have you tried checking this documentation on how to extend an entity? And if so, where did you find it fell short exactly?
Regarding CRUD operations, unfortunately, that's not currently available automatically out of the box. You have to create endpoints for each of these operations. Check out this documentation on how to create an endpoint.
@shahednasser I failed to do following things after extend entity documentations
Expectations:
I need to achieve all these with without writing a new endpoint, as I want to use /store/products
endpoint only
I have explained the same in detail on issue description
I would need your help to find out possible correct way of implementation of same if my approach is not correct or no implementable
ProductService
and maybe extend the listAndCount
method to pass to the parent your field as one of the selectors. You can learn more about extending a service here. You can also learn about the available properties and methods in the ProductService in this reference if you don't want to go through the core code.Closing this issue for lack of response.
Closing this issue for lack of response.
@shahednasser I would like to follow up an this excellent post by the OP.
Im in the process of adding a field invoiced_at
to the order model, I did so successfully and now I want to add a filter for it so I can use it like so: {{medusa-host}}/admin/orders?invoiced_at=2024-01-01
.
I see there's AdminGetOrdersParams
in /node_modules/@medusajs/medusa/dist/api/routes/admin/orders/list-orders.js
as well that we might need to use.
I did the following and can send the query param now, however, it is not working as results are always empty:
import { AdminGetOrdersParams as MedusaAdminGetOrdersParams } from "@medusajs/medusa/dist/api/routes/admin/orders/list-orders"
import { IsDateString, IsOptional } from "class-validator"
export class AdminGetOrdersParams extends MedusaAdminGetOrdersParams {
@IsDateString()
@IsOptional()
invoiced_at: Date
}
And I registered the validator in my index file:
registerOverriddenValidators(AdminGetOrdersParams)
How do I add invoiced_at
as a filter with the same capabilities as the other date filters on List orders: https://docs.medusajs.com/api/admin#orders_getorders (created_at
for example)
Thank you for your comment @shahednasser, I agree I need to pass the param as an object like you said, but for that to be accepted, I first need to write the right validator for that.
And that is where I'm stuck, how do I write that validator so that it accepts ?invoiced_at[lte]=2024-01-01
as now it return error: invoiced_at must be a valid ISO 8601 date string
.
And accepting is part one, part two is that it's actually applied to the query....
I know how to do it on a new custom endpoint, but I want it to work for the existing endpoints.
Actually to use the object the type of the invoiced_at
filter should be DateComparisonOperator
like this:
import { DateComparisonOperator } from "@medusajs/medusa"
import { AdminGetOrdersParams as MedusaAdminGetOrdersParams } from "@medusajs/medusa/dist/api/routes/admin/orders/list-orders"
import { IsDateString, IsOptional } from "class-validator"
export class AdminGetOrdersParams extends MedusaAdminGetOrdersParams {
@IsOptional()
invoiced_at: DateComparisonOperator
}
But that's optional, so I don't think the issue is here.
Maybe @adrien2p would know the issue here? There are certain things that I'm not very familiar with
Using DateComparisonOperator
as type works @shahednasser , thanks! This actually makes it work at all, the whole filter works now!
I just found out this bug https://github.com/medusajs/medusa/issues/6359 which I bump into here again, My date in the table is 2023-08-18 16:28:04.669+02
, when I use ?invoiced_at[lte]=2023-08-19
it returns the order and when I use ?invoiced_at[lte]=2023-08-18
it does not, meaning lte
is not lower than or equal, but lower than....
I now have one more issue left to tackle, which is how to add the invoiced_at
as a default in the reponses. I have the following loader file src/loaders/extend-order-fields.ts
:
export default async function () {
const imports = (await import(
"@medusajs/medusa/dist/api/routes/admin/orders/index"
)) as any
imports.allowedAdminOrdersFields = [
...imports.allowedAdminOrdersFields,
"invoiced_at",
]
imports.defaultAdminOrdersFields = [
...imports.defaultAdminOrdersFields,
"invoiced_at",
]
}
defaultAdminOrdersFields
seems different then the defaultStoreProductsFields
from the example/docs, and my invoiced_at
is not loaded by default. When I look at the /node_modules/@medusajs/medusa/dist/api/routes/admin/orders/index.js
file, I do not see the default fields specified.
How is this done? Would be nice if documented.
@BorisKamp , it is normal that ?invoiced_at[lte]=2023-08-18
does not return your data since by default if you do not specify any hours then I think it will take the first second of the day which is before 2023-08-18 16:28:04.669+02
. You can run a SQL query and the result will be the same.
About the default fields, they are used in the order routes, except that you didn't look where they are imported from :) dist/types/orders.ts
, should be good after that.
cc @shahednasser
Thank you so much @adrien2p makes sense regarding the date filter, I learned from that.
Ah now I see (this is all quite new for me, learning a lot) that defaultAdminOrdersFields
is defined in /dist/types/order.js
indeed. What I did now is the following in my loader file:
export default async function () {
const imports = (await import(
"@medusajs/medusa/dist/api/routes/admin/orders/index"
)) as any
const importTypes = (await import(
"@medusajs/medusa/dist/types/orders"
)) as any
imports.allowedAdminOrdersFields = [
...imports.allowedAdminOrdersFields,
"invoiced_at",
"bb_company_slug"
]
importTypes.defaultAdminOrdersFields = [
...importTypes.defaultAdminOrdersFields,
"invoiced_at",
"bb_company_slug"
]
}
However, the fields are still not returned as default...
@BorisKamp no worries, the reason I think is because you are importing the route index first, which itself import the types already. I would suggest you to first import the types, modify them then import the route and modify what you need there
@BorisKamp no worries, the reason I think is because you are importing the route index first, which itself import the types already. I would suggest you to first import the types, modify them then import the route and modify what you need there
Genius! Thank you so much, so happy now!
@adrien2p one more related question, can we extend the core orders list route with filters that apply on relations such as where cart.customfield === 'value'
or do we need a dedicated new endpoint for that?
@shahednasser @adrien2p @BorisKamp I wanted to filter the products based on options like size or color and size and color would have values like grey, XL respectively. @shahednasser as you said earlier I read the docs and i got a way to add custom field to the existing API as below
import { StoreGetProductsParams as MedusaStoreGetProductsParams } from '@medusajs/medusa/dist/api/routes/store/products/list-products';
import { IsOptional } from 'class-validator';
class StoreGetProductsParams extends MedusaStoreGetProductsParams {
@IsOptional()
subtitle: string;
@IsOptional()
options: Object;
}
registerOverriddenValidators(StoreGetProductsParams);
But im unable to find a way to pass options which has values like Size and Color further having values like grey, Xl etc. Can you guys suggest me a way to do so ?
Preliminary Checks
Issue Summary
Hello team
While exploring MedusaJS, I see that there are default entities are available for any eCommerce application
Like Products, Cart, Orders, Inventory, Payment etc.
But I'm not able to find fine way to extend Product Entity to apply filters (
/store/products
and/store/products/search
)I followed the documentation and looked into the code, I found that I can perform filtering on restricted fields which are maintained in
FilterableProductProps
typemedusajs/medusa/packages/medusa/src/types/product.ts
Possible solutions are
Scenario
Building out a B2B website I have product with 15 options values that creates more than 100 variants combinations Also, each product have more than 50 properties or attributes Each attribute or option looks like
Key:Value
combinationProblem Statement 1
I want to provide filters on 15 options as well as 50+ product attributes I see
store/products
works with certain product properties which are maintainedFilterableProductProps
type Even, I discovered that I can not filter the products by multiple status like 'published' or 'draft'search by options, for example:
options.title[]=size&options.title[]=color&options.values[]=XL&&options.values[]=Blue
search by product attributes/properties, for example:
color[]=Blue&size[]=XL
Problem Statement 2
I have created new entity to save the searches, I was expecting that CRUD options API will be available out of the box for newly created entity but I don't see such options
I can understand the part with logical implementation like Wishlist https://medusajs.com/blog/how-to-create-a-wishlist-with-medusa/#add-wishlist-service
But is there option available where CRUD operations like endpoints for entity?
How can this issue be resolved?
Possible solution for problem statement 1
In this context, I avoid reinventing the wheel by enhancing the current case filtering functionality. I genuinely appreciate the default entity implementation offered by MedusaJS. If I were to code the filtering feature from scratch, it might be somewhat excessive.
I haven't tried out but I see that extending the
FilterableProductProps
type will solve the problemIt will helpful if you provide your insights on the same with small example
End goal will be to implement following functionality, but now looking out simple approach to applying filters on multiple product props or options without reinventing the wheel
Discord Source: Show Products Documentation (https://docs.medusajs.com/modules/products/storefront/show-products#filtering-retrieved-products)
Possible solution for problem statement 2
Is there any possibility where we can enable/disable the basic CRUD operation API endpoints?
Are you interested in working on this issue?