Add product

This commit is contained in:
Niklas Fondberg
2021-04-08 15:09:31 +02:00
parent e0f629d54d
commit f60a51a94b
11 changed files with 184 additions and 171 deletions
+10
View File
@@ -65,8 +65,18 @@
{ {
order(id: 588274) { order(id: 588274) {
id id
marketObject {
id
name
vat
currency
priceAdjustment
}
rows { rows {
id id
order {
id
}
insertedDate insertedDate
orderId orderId
productId productId
+26 -2
View File
@@ -1,6 +1,12 @@
import { SQLDataSource } from 'datasource-sql'; import { SQLDataSource } from 'datasource-sql';
import { camelcase } from 'stringcase'; import { camelcase } from 'stringcase';
import { Address, ContactInformation, Order, OrderRow } from './order-types'; import {
Address,
ContactInformation,
Market,
Order,
OrderRow,
} from './order-types';
import { Maybe } from './types'; import { Maybe } from './types';
const MINUTE = 60; const MINUTE = 60;
@@ -9,6 +15,24 @@ export class OrderAPI extends SQLDataSource {
super(config); super(config);
} }
async getMarketById(id: number): Promise<Market> {
return await this.knex
.select('*')
.from('markets')
.where('id', id)
.first()
.cache(MINUTE);
}
async getMarketByName(name: string): Promise<Market> {
return await this.knex
.select('*')
.from('markets')
.where('name', name)
.first()
.cache(MINUTE);
}
async getAddress(addressId: number): Promise<Maybe<Address>> { async getAddress(addressId: number): Promise<Maybe<Address>> {
const row = await this.knex const row = await this.knex
.select('*') .select('*')
@@ -103,7 +127,6 @@ export class OrderAPI extends SQLDataSource {
} }
const orderRow = details.reduce((obj, item) => { const orderRow = details.reduce((obj, item) => {
obj[camelcase(fields[item.fieldid])] = item.value; obj[camelcase(fields[item.fieldid])] = item.value;
obj['insertedDate'] = item.inserted;
return obj; return obj;
}, {}); }, {});
@@ -120,6 +143,7 @@ export class OrderAPI extends SQLDataSource {
} }
/** /**
* row
{ {
printId: '73963', printId: '73963',
inserted: 2021-02-04T10:11:41.093Z, inserted: 2021-02-04T10:11:41.093Z,
+9 -1
View File
@@ -1,3 +1,11 @@
export interface Market {
id: number;
name: string;
vat: number;
currency: string;
priceAdjustment: number;
}
export interface Address { export interface Address {
id: number; id: number;
firstname: string; firstname: string;
@@ -71,7 +79,7 @@ export interface Order {
export interface OrderRow { export interface OrderRow {
id: number; id: number;
insertedDate: Date; inserted: Date;
orderId: number; orderId: number;
productId: number; productId: number;
productGroup: string; productGroup: string;
+13 -5
View File
@@ -39,21 +39,29 @@ export class ProductAPI extends SQLDataSource {
limit: Maybe<number>, limit: Maybe<number>,
visible: Maybe<boolean>, visible: Maybe<boolean>,
browsable: Maybe<boolean>, browsable: Maybe<boolean>,
): Promise<Product> { ): Promise<Array<Product>> {
// console.log(limit, browsable, visible);
limit = limit ?? 100; limit = limit ?? 100;
const query = sql.products(limit, visible, browsable); const query = sql.products(limit, visible, browsable);
const data = await this.knex.raw(query).then((data) => return await this.knex.raw(query).then((data) =>
data.rows.map((row) => { data.rows.map((row) => {
row.blacklisting = this.getBlacklisting(row); row.blacklisting = this.getBlacklisting(row);
row.printProducts = this.getPrintProducts(row); row.printProducts = this.getPrintProducts(row);
return row; return row;
}), }),
); );
}
// console.log(JSON.stringify(data, null, 2)); async getProduct(id: number): Promise<Maybe<Product>> {
const query = sql.product(id);
return data; const res = await this.knex.raw(query).then((data) =>
data.rows.map((row) => {
row.blacklisting = this.getBlacklisting(row);
row.printProducts = this.getPrintProducts(row);
return row;
}),
);
return res.find(Boolean);
} }
} }
+22 -9
View File
@@ -2,14 +2,9 @@ import { Maybe } from '../types';
// Get syntax highlighting with vscode by installing "Comment tagged templates2 // Get syntax highlighting with vscode by installing "Comment tagged templates2
export function products( const baseQuery = /* sql */ `
limit: number = 100,
visible: Maybe<boolean>,
browsable: Maybe<boolean>,
) {
const query = /* sql */ `
SELECT products.productid as id, SELECT products.productid as id,
products.path, products.path,
products.visible, products.visible,
products.browsable, products.browsable,
@@ -50,6 +45,16 @@ export function products(
) FROM product_blacklist WHERE product_blacklist.product_id = products.productid ) FROM product_blacklist WHERE product_blacklist.product_id = products.productid
) AS blacklisting ) AS blacklisting
FROM "product-products" products FROM "product-products" products
`;
export function products(
limit: number = 100,
visible: Maybe<boolean>,
browsable: Maybe<boolean>,
) {
return (
baseQuery +
/* sql */ `
${ ${
visible != null visible != null
? /* sql */ ` ? /* sql */ `
@@ -58,7 +63,15 @@ export function products(
: `` : ``
} }
LIMIT ${limit} LIMIT ${limit}
`; `
);
}
return query; export function product(id: number) {
return (
baseQuery +
/* sql */ `
WHERE products.productid = ${id}
`
);
} }
-1
View File
@@ -6,7 +6,6 @@ import knexStringcase from 'knex-stringcase';
import { dbConfig } from './config'; import { dbConfig } from './config';
import { typeDefs } from './schema'; import { typeDefs } from './schema';
import resolvers from './resolvers'; import resolvers from './resolvers';
import { OrderAPI } from './datasources/order-api'; import { OrderAPI } from './datasources/order-api';
import { ProductAPI } from './datasources/product-api'; import { ProductAPI } from './datasources/product-api';
+1
View File
@@ -1,6 +1,7 @@
import { GraphQLScalarType } from 'graphql'; import { GraphQLScalarType } from 'graphql';
import { Kind } from 'graphql/language'; import { Kind } from 'graphql/language';
// possible switch to https://github.com/Urigo/graphql-scalars
export const DateTimeScalar = new GraphQLScalarType({ export const DateTimeScalar = new GraphQLScalarType({
name: 'DateTime', name: 'DateTime',
description: 'Date custom scalar type', description: 'Date custom scalar type',
+5 -5
View File
@@ -1,12 +1,12 @@
import orders, { ContactInformation, Order } from './orders-resolver'; import { orderQueryTypeDefs, orderTypeDefs } from './orders-resolver';
import products from './products-resolver'; import { productQueryTypeDefs, productTypeDefs } from './products-resolver';
import { DateTimeScalar } from './datetime-type'; import { DateTimeScalar } from './datetime-type';
const resolvers = { const resolvers = {
Query: { ...orders, ...products }, Query: { ...orderQueryTypeDefs, ...productQueryTypeDefs },
DateTime: DateTimeScalar, DateTime: DateTimeScalar,
ContactInformation, ...orderTypeDefs,
Order, ...productTypeDefs,
}; };
export default resolvers; export default resolvers;
+18 -5
View File
@@ -1,16 +1,25 @@
import { IResolverObject } from 'graphql-tools'; import { IResolverObject } from 'graphql-tools';
export const ContactInformation: IResolverObject = { const ContactInformation: IResolverObject = {
// (parent, args, ctx, info) // (parent, args, ctx, info)
async address({ addressId }, args, { dataSources }) { async address({ addressId }, args, { dataSources }) {
return dataSources.orderApi.getAddress(addressId); return dataSources.orderApi.getAddress(addressId);
}, },
}; };
export const Order: IResolverObject = { const Order: IResolverObject = {
async rows({ id }, args, { dataSources }) { async rows({ id }, args, { dataSources }) {
return dataSources.orderApi.getOrderRows(id); return dataSources.orderApi.getOrderRows(id);
}, },
async marketObject({ market }, args, { dataSources }) {
return dataSources.orderApi.getMarketByName(market);
},
};
const OrderRow: IResolverObject = {
async order(parent, args, { dataSources }) {
return dataSources.orderApi.getOrder(parent.orderId);
},
}; };
async function getOrders(_, __, { dataSources }) { async function getOrders(_, __, { dataSources }) {
@@ -21,9 +30,13 @@ async function getOrder(_, { id }, { dataSources }) {
return dataSources.orderApi.getOrder(id); return dataSources.orderApi.getOrder(id);
} }
const orders = { export const orderTypeDefs = {
ContactInformation,
Order,
OrderRow,
};
export const orderQueryTypeDefs = {
orders: getOrders, orders: getOrders,
order: getOrder, order: getOrder,
}; };
export default orders;
+22 -4
View File
@@ -1,7 +1,25 @@
// (parent, args, ctx, info) // (parent, args, ctx, info)
const products = { import { IResolverObject } from 'graphql-tools';
products: (_, { limit, visible, browsable }, { dataSources }) =>
dataSources.productApi.getProducts(limit, visible, browsable), const ProductBlacklist: IResolverObject = {
async market(parent, args, { dataSources }) {
return dataSources.orderApi.getMarketById(parent.marketId);
},
}; };
export default products; async function getProducts(_, { limit, visible, browsable }, { dataSources }) {
return dataSources.productApi.getProducts(limit, visible, browsable);
}
async function getProduct(_, { id }, { dataSources }) {
return dataSources.productApi.getProduct(id);
}
export const productTypeDefs = {
ProductBlacklist,
};
export const productQueryTypeDefs = {
products: getProducts,
product: getProduct,
};
+21 -102
View File
@@ -7,6 +7,15 @@ const typeDefs = gql`
orders: [Order] orders: [Order]
order(id: ID!): Order order(id: ID!): Order
products(limit: Int, visible: Boolean, browsable: Boolean): [Product] products(limit: Int, visible: Boolean, browsable: Boolean): [Product]
product(id: Int!): Product
}
type Market {
id: ID!
name: String
vat: Float
currency: String
priceAdjustment: Float
} }
type Address { type Address {
@@ -79,12 +88,13 @@ const typeDefs = gql`
billingAddressId: Int billingAddressId: Int
deliveryAddressId: Int deliveryAddressId: Int
rows: [OrderRow] rows: [OrderRow]
marketObject: Market
} }
type OrderRow { type OrderRow {
id: ID! id: ID!
order: Order order: Order
insertedDate: DateTime inserted: DateTime
orderId: Int orderId: Int
productId: Int productId: Int
productGroup: String productGroup: String
@@ -100,6 +110,11 @@ const typeDefs = gql`
pwintySku: String pwintySku: String
} }
type Category {
id: ID!
name: String
}
type Product { type Product {
id: ID! id: ID!
path: String! path: String!
@@ -126,6 +141,7 @@ const typeDefs = gql`
groupId: Int! groupId: Int!
group: ProductGroup! group: ProductGroup!
marketId: Int! marketId: Int!
market: Market!
inserted: DateTime! inserted: DateTime!
updated: DateTime! updated: DateTime!
} }
@@ -141,38 +157,13 @@ const typeDefs = gql`
export { typeDefs }; export { typeDefs };
/** /**
schema {
query: Query
}
type Address {
id: ID!
firstname: String
lastname: String
recipientName: String
companyname: String
address1: String
address2: String
countryCode: String
city: String
zipcode: String
stateCountyOrRegion: String
}
type Category { type Category {
id: ID! id: ID!
name: String name: String
} }
type ContactInformation {
email: String
phone: String
address: Address
}
scalar Date
scalar DateTime
type Designer { type Designer {
id: ID! id: ID!
@@ -180,98 +171,26 @@ type Designer {
orderRows(fromDate: Date, toDate: Date): [OrderRow] orderRows(fromDate: Date, toDate: Date): [OrderRow]
} }
enum Group {
PHOTO_WALLPAPER
CANVAS
WALLPAPER
DO_IT_YOURSELF_FRAME
DESIGNER_WALLPAPER
POSTER
FRAMED_PRINT
}
scalar JSONString
type Market {
id: ID!
name: String
}
type Order {
id: ID!
insertedDate: DateTime!
paid: Boolean!
confirmed: Boolean!
delivered: Boolean!
canceled: Boolean!
countryCode: String!
locale: String!
market: String!
currency: String
contractCustomerId: Int
exchangeRateEUR: Float
language: String
pwintyId: Int
email: String
phone: String
rows: [OrderRow]
billingInformation: ContactInformation
deliveryInformation: ContactInformation
}
type OrderRow {
id: ID!
order: Order
insertedDate: DateTime
orderId: Int
productId: Int
productGroup: String
artNo: String
path: String
name: String
price: Float
designerId: String
commissionAmount: String
status: String
pwintyImageId: Int
frameColor: String
pwintySku: String
json: JSONString
}
type PrintProduct { type PrintProduct {
id: ID!
group: Group!
insertedDate: DateTime! insertedDate: DateTime!
updatedDate: DateTime updatedDate: DateTime
} }
type Product { type Product {
id: ID!
path: String!
visible: Boolean
browsable: Boolean
insertedDate: DateTime!
updatedDate: DateTime!
categories: [Category] categories: [Category]
designer: Designer designer: Designer
printProducts: [PrintProduct] insertedDate: DateTime!
blacklisting: [ProductBlacklist] updatedDate: DateTime
} }
type ProductBlacklist { type ProductBlacklist {
id: ID!
group: Group!
marketId: String!
insertedDate: DateTime!
updatedDate: DateTime!
market: Market market: Market
insertedDate: DateTime!
updatedDate: DateTime
} }
type Query { type Query {
products(limit: Int, visible: Boolean, browsable: Boolean): [Product]
product(id: Int!): Product product(id: Int!): Product
order(id: Int!): Order
designer(id: Int!): Designer designer(id: Int!): Designer
designers: [Designer] designers: [Designer]
} }