Feat: Filter price lists by customer group (#1431)
* add customer groups to price list factory * add integration test for filtering price lists by customer group * normalize list price list query * add customer groups to list-price-list queryparameters * query based on customergroups if they exist for price lists * remove verbose flag * add another price list with a customer group * remove console.log * pr feedback * add query type to repository * add query type to repository * set groups to undefined instead of deleting parameter * remove wildcard destructing * make buildQuery type specific to price lists * steal Adriens types * fix(medusa): support searching for price lists (#1407) * delete instead of settting groups to undefined * add groups to query with q * use simple customer group factory instead of manual creation * Update simple-customer-group-factory.ts * remove comma that breaks integration-tests Co-authored-by: Zakaria El Asri <33696020+zakariaelas@users.noreply.github.com>
This commit is contained in:
co-authored by
Zakaria El Asri
parent
0b2a3a0f0e
commit
a69b52e031
@@ -11,7 +11,11 @@ export default (app) => {
|
||||
|
||||
route.get("/:id", middlewares.wrap(require("./get-price-list").default))
|
||||
|
||||
route.get("/", middlewares.wrap(require("./list-price-lists").default))
|
||||
route.get(
|
||||
"/",
|
||||
middlewares.normalizeQuery(),
|
||||
middlewares.wrap(require("./list-price-lists").default)
|
||||
)
|
||||
|
||||
route.get(
|
||||
"/:id/products",
|
||||
|
||||
@@ -2,22 +2,26 @@ import { groupBy, map } from "lodash"
|
||||
import {
|
||||
Brackets,
|
||||
EntityRepository,
|
||||
FindManyOptions, Repository
|
||||
FindManyOptions,
|
||||
FindOperator,
|
||||
Repository,
|
||||
} from "typeorm"
|
||||
import { PriceList } from "../models/price-list"
|
||||
import { CustomFindOptions } from "../types/common"
|
||||
import { CustomFindOptions, ExtendedFindConfig } from "../types/common"
|
||||
|
||||
type PriceListFindOptions = CustomFindOptions<PriceList, 'status' | 'type'>
|
||||
type PriceListFindOptions = CustomFindOptions<PriceList, "status" | "type">
|
||||
|
||||
@EntityRepository(PriceList)
|
||||
export class PriceListRepository extends Repository<PriceList> {
|
||||
public async getFreeTextSearchResultsAndCount(
|
||||
q: string,
|
||||
options: PriceListFindOptions = { where: {} },
|
||||
groups?: FindOperator<PriceList>,
|
||||
relations: (keyof PriceList)[] = []
|
||||
): Promise<[PriceList[], number]> {
|
||||
options.where = options.where ?? {}
|
||||
let qb = this.createQueryBuilder("price_list")
|
||||
|
||||
const qb = this.createQueryBuilder("price_list")
|
||||
.leftJoinAndSelect("price_list.customer_groups", "customer_group")
|
||||
.select(["price_list.id"])
|
||||
.where(options.where)
|
||||
@@ -31,6 +35,10 @@ export class PriceListRepository extends Repository<PriceList> {
|
||||
.skip(options.skip)
|
||||
.take(options.take)
|
||||
|
||||
if (groups) {
|
||||
qb.andWhere("group.id IN (:...ids)", { ids: groups.value })
|
||||
}
|
||||
|
||||
const [results, count] = await qb.getManyAndCount()
|
||||
|
||||
const price_lists = await this.findWithRelations(
|
||||
@@ -53,7 +61,6 @@ export class PriceListRepository extends Repository<PriceList> {
|
||||
} else {
|
||||
entities = await this.find(idsOrOptionsWithoutRelations)
|
||||
}
|
||||
|
||||
const groupedRelations: Record<string, string[]> = {}
|
||||
for (const relation of relations) {
|
||||
const [topLevel] = relation.split(".")
|
||||
@@ -63,7 +70,6 @@ export class PriceListRepository extends Repository<PriceList> {
|
||||
groupedRelations[topLevel] = [relation]
|
||||
}
|
||||
}
|
||||
|
||||
const entitiesIds = entities.map(({ id }) => id)
|
||||
const entitiesIdsWithRelations = await Promise.all(
|
||||
Object.values(groupedRelations).map((relations: string[]) => {
|
||||
@@ -72,7 +78,7 @@ export class PriceListRepository extends Repository<PriceList> {
|
||||
relations: relations as string[],
|
||||
})
|
||||
})
|
||||
).then(entitiesIdsWithRelations => entitiesIdsWithRelations.flat())
|
||||
).then((entitiesIdsWithRelations) => entitiesIdsWithRelations.flat())
|
||||
const entitiesAndRelations = entitiesIdsWithRelations.concat(entities)
|
||||
|
||||
const entitiesAndRelationsById = groupBy(entitiesAndRelations, "id")
|
||||
@@ -87,9 +93,31 @@ export class PriceListRepository extends Repository<PriceList> {
|
||||
): Promise<PriceList | undefined> {
|
||||
options.take = 1
|
||||
|
||||
return (await this.findWithRelations(
|
||||
relations,
|
||||
options
|
||||
))?.pop()
|
||||
return (await this.findWithRelations(relations, options))?.pop()
|
||||
}
|
||||
|
||||
async listAndCount(
|
||||
query: ExtendedFindConfig<PriceList>,
|
||||
groups?: FindOperator<PriceList>
|
||||
): Promise<[PriceList[], number]> {
|
||||
const qb = this.createQueryBuilder("price_list")
|
||||
.where(query.where)
|
||||
.skip(query.skip)
|
||||
.take(query.take)
|
||||
|
||||
if (groups) {
|
||||
qb.leftJoinAndSelect("price_list.customer_groups", "group").andWhere(
|
||||
"group.id IN (:...ids)",
|
||||
{ ids: groups.value }
|
||||
)
|
||||
}
|
||||
|
||||
if (query.relations?.length) {
|
||||
query.relations.forEach((rel) => {
|
||||
qb.leftJoinAndSelect(`price_list.${rel}`, rel)
|
||||
})
|
||||
}
|
||||
|
||||
return await qb.getManyAndCount()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -252,10 +252,18 @@ class PriceListService extends BaseService {
|
||||
selector: FilterablePriceListProps = {},
|
||||
config: FindConfig<PriceList> = { skip: 0, take: 20 }
|
||||
): Promise<PriceList[]> {
|
||||
const priceListRepo = this.manager_.getCustomRepository(this.priceListRepo_)
|
||||
return await this.atomicPhase_(async (manager: EntityManager) => {
|
||||
const priceListRepo = manager.getCustomRepository(this.priceListRepo_)
|
||||
|
||||
const query = this.buildQuery_(selector, config)
|
||||
return await priceListRepo.find(query)
|
||||
const query = this.buildQuery_(selector, config)
|
||||
|
||||
const groups = query.where.customer_groups
|
||||
query.where.customer_groups = undefined
|
||||
|
||||
const [priceLists] = await priceListRepo.listAndCount(query, groups)
|
||||
|
||||
return priceLists
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -268,19 +276,25 @@ class PriceListService extends BaseService {
|
||||
selector: FilterablePriceListProps = {},
|
||||
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)
|
||||
return await this.atomicPhase_(async (manager: EntityManager) => {
|
||||
const priceListRepo = manager.getCustomRepository(this.priceListRepo_)
|
||||
const q = selector.q
|
||||
const { relations, ...query } = this.buildQuery_(selector, config)
|
||||
|
||||
if (q) {
|
||||
delete query.where.q
|
||||
return await priceListRepo.getFreeTextSearchResultsAndCount(
|
||||
q,
|
||||
query,
|
||||
relations
|
||||
)
|
||||
}
|
||||
return await priceListRepo.findAndCount({ ...query, relations })
|
||||
const groups = query.where.customer_groups
|
||||
delete query.where.customer_groups
|
||||
|
||||
if (q) {
|
||||
delete query.where.q
|
||||
return await priceListRepo.getFreeTextSearchResultsAndCount(
|
||||
q,
|
||||
query,
|
||||
groups,
|
||||
relations
|
||||
)
|
||||
}
|
||||
return await priceListRepo.listAndCount({ ...query, relations }, groups)
|
||||
})
|
||||
}
|
||||
|
||||
async upsertCustomerGroups_(
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
ValidateNested,
|
||||
} from "class-validator"
|
||||
import { PriceList } from "../models/price-list"
|
||||
import { DateComparisonOperator } from "./common"
|
||||
import { DateComparisonOperator, FindConfig } from "./common"
|
||||
import { XorConstraint } from "./validators/xor"
|
||||
|
||||
export enum PriceListType {
|
||||
@@ -39,6 +39,10 @@ export class FilterablePriceListProps {
|
||||
@IsOptional()
|
||||
name?: string
|
||||
|
||||
@IsOptional()
|
||||
@IsString({ each: true })
|
||||
customer_groups?: string[]
|
||||
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
description?: string
|
||||
|
||||
Reference in New Issue
Block a user