diff --git a/src/datasources/product-api.ts b/src/datasources/product-api.ts index cb9d480..bfb040f 100644 --- a/src/datasources/product-api.ts +++ b/src/datasources/product-api.ts @@ -203,7 +203,10 @@ export class ProductAPI extends BaseSQLDataSource { Scopes.PRODUCTS_PUBLIC_READ, ]); const query = sql.productsTotal(input); - const res = await this.cachedRaw(query, null) + + const variables = input.filter?.ids ? input.filter.ids : []; + + const res = await this.cachedRaw(query, variables) .cache(MINUTE * 5) .then((data) => data.rows); return res[0]['count'] as number; // Optimize later to return Promise @@ -216,8 +219,10 @@ export class ProductAPI extends BaseSQLDataSource { ]); const query = sql.products(input); + const variables = input.filter?.ids ? input.filter.ids : []; + return this.knex - .raw(query) + .raw(query, variables) .then((data) => data.rows.map((row) => this.createProductFromRow(row))); } diff --git a/src/datasources/sql/products-sql.ts b/src/datasources/sql/products-sql.ts index 851d5ff..334fd2e 100644 --- a/src/datasources/sql/products-sql.ts +++ b/src/datasources/sql/products-sql.ts @@ -1,4 +1,5 @@ -import { ProductsFilterInput } from '../../types/product-types'; +import { ProductsFilter, ProductsFilterInput } from '../../types/product-types'; +import { createQuestionMarksFromList } from '../utils'; // Get syntax highlighting with vscode by installing "Comment tagged templates2 @@ -76,38 +77,61 @@ FROM "product-products" products LEFT JOIN stockproducts stock ON stock.product_id = products.productid `; +const addFiltersToQuery = (baseQuery: string, filter: ProductsFilter) => { + if (!filter) { + return baseQuery; + } + if ('browsable' in filter || 'visible' in filter || 'ids' in filter) { + let query = /* sql */ `${baseQuery} WHERE`; + + if ('browsable' in filter) { + query = /* sql */ `${query} products.browsable = ${ + filter.browsable ? '1' : '0' + }`; + } + + if ('visible' in filter) { + if ('browsable' in filter) { + query = /* sql */ `${query} AND`; + } + query = /* sql */ `${query} products.visible = ${ + filter.visible ? '1' : '0' + }`; + } + + if ('ids' in filter) { + if ('browsable' in filter || 'visible' in filter) { + query = /* sql */ `${query} AND`; + } + query = /* sql */ `${query} products.productid IN (${createQuestionMarksFromList( + filter.ids, + )})`; + } + return query; + } +}; + export function products(input: ProductsFilterInput) { const limit = input.pagination.limit ?? 100; const offset = input.pagination.offset ?? 0; const filter = input.filter ?? null; - return ( - baseQuery + - /* sql */ ` - ${ - filter?.visible != null - ? /* sql */ ` - WHERE products.visible = ${filter?.visible ? '1' : '0'} - AND products.browsable = ${filter?.browsable ? '1' : '0'}` - : `` - } -ORDER BY products.publishing_date DESC, products.productid DESC -LIMIT ${limit} OFFSET ${offset} -` - ); + + const query = addFiltersToQuery(baseQuery, filter); + + return /* sql */ ` + ${query} + ORDER BY products.publishing_date DESC, products.productid DESC + LIMIT ${limit} OFFSET ${offset} + `; } export function productsTotal(input: ProductsFilterInput) { const filter = input.filter; - return /*sql */ ` - SELECT count(*) FROM "product-products" products - ${ - filter?.visible != null - ? /* sql */ ` - WHERE products.visible = ${filter?.visible ? '1' : '0'} - AND products.browsable = ${filter?.browsable ? '1' : '0'}` - : `` - } + const query = /*sql */ ` + SELECT count(*) FROM "product-products" products `; + + return addFiltersToQuery(query, filter); } export function product() { diff --git a/src/schema.graphql b/src/schema.graphql index 8d94293..d060bd1 100644 --- a/src/schema.graphql +++ b/src/schema.graphql @@ -78,6 +78,7 @@ input DateFilterInput { input ProductsFilterInput { visible: Boolean browsable: Boolean + ids: [Int] } type PaginationResult { diff --git a/src/types/product-types.ts b/src/types/product-types.ts index 5f10c00..d4a6320 100644 --- a/src/types/product-types.ts +++ b/src/types/product-types.ts @@ -47,6 +47,7 @@ export interface ProductsFilterInput { export interface ProductsFilter { visible?: boolean; browsable?: boolean; + ids?: number[]; } export interface ProductsSearchResult {