P5 7619 refactor products to return list (#11)

This commit is contained in:
Niklas Fondberg
2021-08-20 08:16:01 +02:00
committed by GitHub
parent 234996abfd
commit 964a904f42
15 changed files with 235 additions and 92 deletions
+9
View File
@@ -0,0 +1,9 @@
publish-to-staging:
@current_branch=$$(git rev-parse --abbrev-ref HEAD); \
git branch -D staging 2>/dev/null; \
git checkout -b staging; \
git merge $$current_branch && \
git push -f origin staging && \
git checkout $$current_branch; \
echo Pushed $$current_branch to staging
+45
View File
@@ -339,3 +339,48 @@
priceAdjustment
}
}
# for pwinty
{
order(id: 562333) {
id
pwintyId
locale {
value
}
deliveryInformation {
address {
recipientName
companyname
address1
address2
city
countryCode
stateCountyOrRegion
zipcode
}
email
phone
}
billingInformation {
address {
recipientName
companyname
address1
address2
city
countryCode
stateCountyOrRegion
zipcode
}
email
phone
}
rows {
id
pwintySku
pwintyImageId
frameColor
}
}
}
+2 -2
View File
@@ -114,7 +114,7 @@ describe('GraphQL Apollo tests', () => {
id
name
path
orderRows {
orderRows(pagination: {limit: 1000}) {
name
artNo
}
@@ -156,7 +156,7 @@ describe('GraphQL Apollo tests', () => {
id
name
path
orderRows {
orderRows(pagination: {limit: 1000}) {
name,
artNo
}
+13 -14
View File
@@ -6,7 +6,7 @@ import {
Order,
OrderRow,
} from '../types/order-types';
import { GeneralInput, Maybe } from '../types/types';
import { DateFilterInput, GeneralInput, Maybe } from '../types/types';
import { convertToPossibleType } from './utils';
import { getProductGroupStringFromString } from '../types/product-types';
@@ -54,10 +54,9 @@ export class OrderAPI extends BaseSQLDataSource {
}
createOrderFromRow(row: any): Order {
row.__resolveType = 'Order';
row.billingInformation = this.getBillingInformation(row);
row.deliveryInformation = this.getDeliveryInformation(row);
row.marketName = row.market;
row.localeName = row.locale;
return row;
}
@@ -71,11 +70,9 @@ export class OrderAPI extends BaseSQLDataSource {
}
async getOrders(input: Maybe<GeneralInput>): Promise<Array<Order>> {
let query = this.getOrdersQuery(input);
let query = this.getOrdersQuery(input).limit(input?.pagination.limit);
if (input?.limit) {
query = query.limit(input?.limit);
}
// TODO: handle offset
query = query.orderBy('inserted', 'ASC');
return query
.cache(MINUTE)
@@ -84,12 +81,12 @@ export class OrderAPI extends BaseSQLDataSource {
private getOrdersQuery(input: GeneralInput) {
let query = this.knex.table('orders');
if (input?.dates?.from) {
query = query.where('inserted', '>=', input.dates.from);
if (input?.filter?.dates?.from) {
query = query.where('inserted', '>=', input.filter.dates.from);
}
if (input?.dates?.to) {
query = query.where('inserted', '<=', input.dates.to);
if (input?.filter?.dates?.to) {
query = query.where('inserted', '<=', input.filter.dates.to);
}
return query;
@@ -190,14 +187,16 @@ export class OrderAPI extends BaseSQLDataSource {
AND orderdetails.inserted >= ?
AND orderdetails.inserted <= ?
ORDER BY orderdetails.inserted ASC
${input?.limit ? `LIMIT ${input.limit}` : ''}
${input?.pagination.limit ? `LIMIT ${input.pagination.limit}` : ''}
`;
const from = input?.dates?.from ? input.dates.from : new Date('2000-01-01');
const from = input?.filter?.dates?.from
? input.filter.dates.from
: new Date('2000-01-01');
const tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);
const to = input?.dates?.to ? input.dates.to : tomorrow; // Tomorrow
const to = input?.filter?.dates?.to ? input.filter?.dates.to : tomorrow; // Tomorrow
const rows = await this.knex
.raw(query, [designerId, this.getSQLDate(from), this.getSQLDate(to)])
+17 -8
View File
@@ -10,6 +10,8 @@ import {
ProductWallpaperType,
ProductFields,
Orientation,
ProductsFilter,
ProductsFilterInput,
} from '../types/product-types';
import { Maybe } from '../types/types';
import { convertToPossibleType } from './utils';
@@ -67,6 +69,9 @@ export class ProductAPI extends BaseSQLDataSource {
}
getProductFields(row: any): ProductFields {
if (!row.fields) {
return null; // 53460 for example
}
const fields = Object.keys(row.fields).reduce((mem, key) => {
mem[camelcase(key)] = convertToPossibleType(row.fields[key]);
return mem;
@@ -76,7 +81,7 @@ export class ProductAPI extends BaseSQLDataSource {
}
getOrientation(fields: ProductFields): string {
if (!fields.width || !fields.height) {
if (!fields || !fields.width || !fields.height) {
return Orientation[Orientation.UNKNOWN];
}
if (fields.width > fields.height) {
@@ -100,13 +105,17 @@ export class ProductAPI extends BaseSQLDataSource {
return row;
}
async getProducts(
limit: Maybe<number>,
visible: Maybe<boolean>,
browsable: Maybe<boolean>,
): Promise<Array<Product>> {
limit = limit ?? 100;
const query = sql.products(limit, visible, browsable);
async getProductsTotal(input: ProductsFilterInput): Promise<number> {
const query = sql.productsTotal(input);
const res = await this.cachedRaw(query)
.cache(MINUTE * 60)
.then((data) => data.rows);
return convertToPossibleType(res[0]['count']); // Optimize later to return Promise
}
async getProducts(input: ProductsFilterInput): Promise<Array<Product>> {
// TODO: handle offset
const query = sql.products(input);
return this.knex
.raw(query)
+21 -8
View File
@@ -1,3 +1,4 @@
import { ProductsFilter, ProductsFilterInput } from '../../types/product-types';
import { Maybe } from '../../types/types';
// Get syntax highlighting with vscode by installing "Comment tagged templates2
@@ -75,19 +76,17 @@ FROM "product-products" products
LEFT JOIN "product-stockproducts" stock ON stock.productid = products.productid
`;
export function products(
limit: number = 100,
visible: Maybe<boolean>,
browsable: Maybe<boolean>,
) {
export function products(input: ProductsFilterInput) {
const limit = input.pagination.limit ?? 100;
const filter = input.filter;
return (
baseQuery +
/* sql */ `
${
visible != null
filter.visible != null
? /* sql */ `
WHERE products.visible = ${visible ? '1' : '0'}
AND products.browsable = ${browsable ? '1' : '0'}`
WHERE products.visible = ${filter?.visible ? '1' : '0'}
AND products.browsable = ${filter?.browsable ? '1' : '0'}`
: ``
}
LIMIT ${limit}
@@ -95,6 +94,20 @@ LIMIT ${limit}
);
}
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'}`
: ``
}
`;
}
export function product(id: number) {
return (
baseQuery +
+1 -1
View File
@@ -65,7 +65,7 @@ async function main() {
dataSources,
context,
introspection: true,
playground: false,
playground: true,
});
await server.listen();
+3 -6
View File
@@ -1,14 +1,11 @@
import { IResolverObject } from 'graphql-tools';
import { DesignerAPI } from '../datasources/designer-api';
import { OrderAPI } from '../datasources/order-api';
import { FilterInput } from '../types/types';
import { GeneralInput } from '../types/types';
const Designer: IResolverObject = {
async orderRows({ id }, args: FilterInput, { dataSources }) {
return (<OrderAPI>dataSources.orderApi).getOrderRowsByDesignerId(
id,
args.filter,
);
async orderRows({ id }, input: GeneralInput, { dataSources }) {
return (<OrderAPI>dataSources.orderApi).getOrderRowsByDesignerId(id, input);
},
};
+14 -5
View File
@@ -1,7 +1,8 @@
import { IResolverObject } from 'graphql-tools';
import { MarketLocaleAPI } from '../datasources/market-locale-api';
import { OrderAPI } from '../datasources/order-api';
import { FilterInput } from '../types/types';
import { OrdersResult } from '../types/order-types';
import { GeneralInput } from '../types/types';
const ContactInformation: IResolverObject = {
// (parent, args, ctx, info)
@@ -32,12 +33,20 @@ const OrderRow: IResolverObject = {
},
};
async function getOrdersResult(_, args: FilterInput, { dataSources }) {
const total = (<OrderAPI>dataSources.orderApi).getOrdersTotal(args.filter);
const items = (<OrderAPI>dataSources.orderApi).getOrders(args.filter);
async function getOrdersResult(
_,
input: GeneralInput,
{ dataSources },
): Promise<OrdersResult> {
const total = (<OrderAPI>dataSources.orderApi).getOrdersTotal(input);
const items = (<OrderAPI>dataSources.orderApi).getOrders(input);
return {
total: total,
items: items,
pagination: {
total: total,
limit: input.pagination.limit,
offset: 0, // TODO: this will be implemented later if the client app needs it
},
};
}
+22 -12
View File
@@ -1,6 +1,10 @@
import { IResolverObject } from 'graphql-tools';
import { ProductAPI } from '../datasources/product-api';
import { Product } from '../types/product-types';
import {
Product,
ProductListResult,
ProductsFilterInput,
} from '../types/product-types';
import { CategoryAPI } from '../datasources/category-api';
import { Category } from '../types/category-types';
import { KeywordAPI } from '../datasources/keyword-api';
@@ -21,7 +25,7 @@ const Product: IResolverObject = {
async categories({ id }, _args, { dataSources }): Promise<Array<Category>> {
return (<CategoryAPI>dataSources.categoryApi).getProductCategories(id);
},
async designer({ designerId }, args, { dataSources }) {
async designer({ designerId }, _args, { dataSources }) {
if (!designerId) {
return null;
}
@@ -41,16 +45,22 @@ const PrintProduct: IResolverObject = {
},
};
async function getProducts(
async function getProductsResult(
_,
{ limit, visible, browsable },
input: ProductsFilterInput,
{ dataSources },
): Promise<Array<Product>> {
return (<ProductAPI>dataSources.productApi).getProducts(
limit,
visible,
browsable,
);
): Promise<ProductListResult> {
const total = (<ProductAPI>dataSources.productApi).getProductsTotal(input);
const items = (<ProductAPI>dataSources.productApi).getProducts(input);
return {
pagination: {
limit: input.pagination.limit,
offset: 0, // TODO: this will be implemented later if the client app needs it
total: total,
},
items: items,
};
}
async function getProduct(_, { id }, { dataSources }): Promise<Product> {
@@ -64,11 +74,11 @@ export const productTypeDefs = {
};
export const productQueryTypeDefs = {
products: getProducts,
products: getProductsResult,
product: getProduct,
};
// Mutations below
// Mutations below, embryo stage
export const productMutationTypeDefs = {
addKeyword(_, { productId, keywordId }, { dataSources }) {
+49 -30
View File
@@ -6,12 +6,12 @@ const typeDefs = gql`
scalar JSON
type Query {
orders(filter: FilterInput!): OrderResult
orders(pagination: PaginationInput!, filter: DateFilterInput!): OrdersResult
order(id: ID!): Order
"""
Will be replaced with a ProductsResult type similar to OrdersResult but we need to change in the similar-images code then
"""
products(limit: Int, visible: Boolean, browsable: Boolean): [Product]
products(
pagination: PaginationInput!
filter: ProductsFilterInput!
): ProductsResult
product(id: Int!): Product
categories: [Category]
category(id: Int!): Category
@@ -26,12 +26,42 @@ const typeDefs = gql`
interiors(filter: InteriorsFilterInput): [Interior]
}
type Mutation {
addKeyword(productId: Int!, keywordId: Int!): MutationResult
input PaginationInput {
limit: Int!
"""
offset is not implemented yet and result will always return as if it was 0. Implement when needed.
"""
offset: Int
}
type MutationResult {
result: String!
input DateInput {
from: Date!
to: Date!
}
input DateFilterInput {
dates: DateInput
}
input ProductsFilterInput {
visible: Boolean
browsable: Boolean
}
type PaginationResult {
total: Int!
offset: Int!
limit: Int!
}
type OrdersResult {
pagination: PaginationResult!
items: [Order]
}
type ProductsResult {
pagination: PaginationResult!
items: [Product]
}
"""
@@ -43,26 +73,6 @@ const typeDefs = gql`
orientation: Orientation!
}
input DateInput {
from: Date
to: Date
}
input FilterInput {
dates: DateInput
limit: Int!
offset: Int!
}
"""
Later replace with implements ListResult when products support it
"""
type OrderResult {
total: Int!
offset: Int
limit: Int
items: [Order]
}
type Market {
id: ID!
name: String!
@@ -342,7 +352,7 @@ const typeDefs = gql`
id: ID!
name: String
path: String
orderRows(filter: FilterInput): [OrderRow]
orderRows(pagination: PaginationInput!, filter: DateFilterInput): [OrderRow]
}
enum KeywordType {
@@ -356,6 +366,15 @@ const typeDefs = gql`
type: KeywordType
products: [Product]
}
# Mutations below
type Mutation {
addKeyword(productId: Int!, keywordId: Int!): MutationResult
}
type MutationResult {
result: String!
}
`;
export { typeDefs };
+7
View File
@@ -1,3 +1,10 @@
import { PaginationResult } from './types';
export interface OrdersResult {
pagination: PaginationResult;
items: Array<Order> | Promise<Array<Order>>;
}
export interface Address {
id: number;
firstname: string;
+16
View File
@@ -1,3 +1,19 @@
import { PaginationInput, PaginationResult } from './types';
export interface ProductsFilterInput {
pagination: PaginationInput;
filter?: ProductsFilter;
}
export interface ProductsFilter {
visible?: boolean;
browsable?: boolean;
}
export interface ProductListResult {
pagination: PaginationResult;
items: Array<Product> | Promise<Array<Product>>;
}
export enum ProductGroup {
PHOTO_WALLPAPER = 1,
CANVAS = 2,
+15 -5
View File
@@ -1,16 +1,26 @@
export type Maybe<T> = T | undefined;
export interface PaginationInput {
limit: number;
offset?: number;
}
export interface DateInput {
from: Date;
to: Date;
}
export interface GeneralInput {
export interface DateFilterInput {
dates: DateInput;
limit: number;
offset: number;
}
export interface FilterInput {
filter: GeneralInput;
export interface GeneralInput {
pagination: PaginationInput;
filter?: DateFilterInput;
}
export interface PaginationResult {
total: Promise<number> | number;
offset: number;
limit: number;
}