fix(medusa): support searching for price lists (#1407)
This commit is contained in:
@@ -1,5 +1,95 @@
|
||||
import { EntityRepository, Repository } from "typeorm"
|
||||
import { groupBy, map } from "lodash"
|
||||
import {
|
||||
Brackets,
|
||||
EntityRepository,
|
||||
FindManyOptions, Repository
|
||||
} from "typeorm"
|
||||
import { PriceList } from "../models/price-list"
|
||||
import { CustomFindOptions } from "../types/common"
|
||||
|
||||
type PriceListFindOptions = CustomFindOptions<PriceList, 'status' | 'type'>
|
||||
|
||||
@EntityRepository(PriceList)
|
||||
export class PriceListRepository extends Repository<PriceList> {}
|
||||
export class PriceListRepository extends Repository<PriceList> {
|
||||
public async getFreeTextSearchResultsAndCount(
|
||||
q: string,
|
||||
options: PriceListFindOptions = { where: {} },
|
||||
relations: (keyof PriceList)[] = []
|
||||
): Promise<[PriceList[], number]> {
|
||||
options.where = options.where ?? {}
|
||||
let qb = this.createQueryBuilder("price_list")
|
||||
.leftJoinAndSelect("price_list.customer_groups", "customer_group")
|
||||
.select(["price_list.id"])
|
||||
.where(options.where)
|
||||
.andWhere(
|
||||
new Brackets((qb) => {
|
||||
qb.where(`price_list.description ILIKE :q`, { q: `%${q}%` })
|
||||
.orWhere(`price_list.name ILIKE :q`, { q: `%${q}%` })
|
||||
.orWhere(`customer_group.name ILIKE :q`, { q: `%${q}%` })
|
||||
})
|
||||
)
|
||||
.skip(options.skip)
|
||||
.take(options.take)
|
||||
|
||||
const [results, count] = await qb.getManyAndCount()
|
||||
|
||||
const price_lists = await this.findWithRelations(
|
||||
relations,
|
||||
results.map((r) => r.id)
|
||||
)
|
||||
|
||||
return [price_lists, count]
|
||||
}
|
||||
|
||||
public async findWithRelations(
|
||||
relations: (keyof PriceList)[] = [],
|
||||
idsOrOptionsWithoutRelations:
|
||||
| Omit<FindManyOptions<PriceList>, "relations">
|
||||
| string[] = {}
|
||||
): Promise<PriceList[]> {
|
||||
let entities
|
||||
if (Array.isArray(idsOrOptionsWithoutRelations)) {
|
||||
entities = await this.findByIds(idsOrOptionsWithoutRelations)
|
||||
} else {
|
||||
entities = await this.find(idsOrOptionsWithoutRelations)
|
||||
}
|
||||
|
||||
const groupedRelations: Record<string, string[]> = {}
|
||||
for (const relation of relations) {
|
||||
const [topLevel] = relation.split(".")
|
||||
if (groupedRelations[topLevel]) {
|
||||
groupedRelations[topLevel].push(relation)
|
||||
} else {
|
||||
groupedRelations[topLevel] = [relation]
|
||||
}
|
||||
}
|
||||
|
||||
const entitiesIds = entities.map(({ id }) => id)
|
||||
const entitiesIdsWithRelations = await Promise.all(
|
||||
Object.values(groupedRelations).map((relations: string[]) => {
|
||||
return this.findByIds(entitiesIds, {
|
||||
select: ["id"],
|
||||
relations: relations as string[],
|
||||
})
|
||||
})
|
||||
).then(entitiesIdsWithRelations => entitiesIdsWithRelations.flat())
|
||||
const entitiesAndRelations = entitiesIdsWithRelations.concat(entities)
|
||||
|
||||
const entitiesAndRelationsById = groupBy(entitiesAndRelations, "id")
|
||||
return map(entitiesAndRelationsById, (entityAndRelations) =>
|
||||
this.merge(this.create(), ...entityAndRelations)
|
||||
)
|
||||
}
|
||||
|
||||
public async findOneWithRelations(
|
||||
relations: (keyof PriceList)[] = [],
|
||||
options: Omit<FindManyOptions<PriceList>, "relations"> = {}
|
||||
): Promise<PriceList | undefined> {
|
||||
options.take = 1
|
||||
|
||||
return (await this.findWithRelations(
|
||||
relations,
|
||||
options
|
||||
))?.pop()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -260,9 +260,18 @@ class PriceListService extends BaseService {
|
||||
config: FindConfig<PriceList> = { skip: 0, take: 20 }
|
||||
): Promise<[PriceList[], number]> {
|
||||
const priceListRepo = this.manager_.getCustomRepository(this.priceListRepo_)
|
||||
const q = selector.q
|
||||
const { relations, ...query } = this.buildQuery_(selector, config)
|
||||
|
||||
const query = this.buildQuery_(selector, config)
|
||||
return await priceListRepo.findAndCount(query)
|
||||
if (q) {
|
||||
delete query.where.q
|
||||
return await priceListRepo.getFreeTextSearchResultsAndCount(
|
||||
q,
|
||||
query,
|
||||
relations
|
||||
)
|
||||
}
|
||||
return await priceListRepo.findAndCount({ ...query, relations })
|
||||
}
|
||||
|
||||
async upsertCustomerGroups_(
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
import { Transform, Type } from "class-transformer"
|
||||
import { IsDate, IsNumber, IsOptional, IsString } from "class-validator"
|
||||
import "reflect-metadata"
|
||||
import {
|
||||
BaseEntity,
|
||||
FindManyOptions,
|
||||
FindOperator,
|
||||
OrderByCondition,
|
||||
} from "typeorm"
|
||||
import { transformDate } from "../utils/validators/date-transform"
|
||||
|
||||
export type PartialPick<T, K extends keyof T> = {
|
||||
@@ -25,6 +31,17 @@ export interface FindConfig<Entity> {
|
||||
order?: Record<string, "ASC" | "DESC">
|
||||
}
|
||||
|
||||
export interface CustomFindOptions<TModel, InKeys extends keyof TModel> {
|
||||
select?: FindManyOptions<TModel>["select"]
|
||||
where?: FindManyOptions<TModel>["where"] &
|
||||
{
|
||||
[P in InKeys]?: TModel[P][]
|
||||
}
|
||||
order?: OrderByCondition
|
||||
skip?: number
|
||||
take?: number
|
||||
}
|
||||
|
||||
export type PaginatedResponse = { limit: number; offset: number; count: number }
|
||||
|
||||
export type DeleteResponse = {
|
||||
|
||||
Reference in New Issue
Block a user