Major refactor

This commit is contained in:
Niklas Fondberg
2021-07-06 15:57:22 +02:00
parent 6bca11c62d
commit f66dbe33d7
21 changed files with 299 additions and 73 deletions
+20
View File
@@ -0,0 +1,20 @@
import { RESTDataSource } from 'apollo-datasource-rest';
export class Api1DataSource extends RESTDataSource {
authHeader: string;
constructor() {
super();
this.baseURL = 'http://docker.for.mac.localhost:8082';
this.authHeader = 'Basic ZGV2OmRldg==';
}
willSendRequest(request) {
request.headers.set('Authorization', this.authHeader);
}
async getProduct(id) {
return await this.get(`/products/${id}?` + new URLSearchParams({}), null, {
cacheOptions: { ttl: 5 },
});
}
}
+60
View File
@@ -0,0 +1,60 @@
import { SQLDataSource } from 'datasource-sql';
import { Category } from '../types/category-types';
const MINUTE = 60;
export class CategoryAPI extends SQLDataSource {
constructor(config) {
super(config);
}
async getProductCategories(productId: number): Promise<Array<Category>> {
const query = /* sql */ `
SELECT product_category.category_id as id,
categories.*
FROM product_category
JOIN v_categorytree categories ON product_category.category_id = categories.id
WHERE product_category.product_id = ?
`;
const res = await this.knex.raw(query, productId).then((data) =>
data.rows.map((row) => {
return {
...row,
path: row.path.replace(/^root/, ''),
};
}),
);
return res;
}
async getCategories(): Promise<Array<Category>> {
return await this.knex
.select('*')
.from('v_categorytree')
.cache(MINUTE)
.then((rows) => {
return rows.map((row) => {
return {
...row,
path: row.path.replace(/^root/, ''),
};
});
});
}
async getCategoryById(id: number): Promise<Category> {
return await this.knex
.select('*')
.from('v_categorytree')
.where('id', id)
.first()
.cache(MINUTE)
.then((row) => {
return {
...row,
path: row.path.replace(/^root/, ''),
};
});
}
}
+2 -2
View File
@@ -1,6 +1,6 @@
import { BaseSQLDataSource } from './BaseSQLDataSource';
import { Designer } from './designer-types';
import { Maybe } from './types';
import { Designer } from '../types/designer-types';
import { Maybe } from '../types/types';
const MINUTE = 60;
export class DesignerAPI extends BaseSQLDataSource {
-5
View File
@@ -1,5 +0,0 @@
export interface Designer {
id: number;
name: string;
path: string;
}
+28 -9
View File
@@ -6,10 +6,10 @@ import {
Market,
Order,
OrderRow,
} from './order-types';
import { GeneralInput, Maybe } from './types';
} from '../types/order-types';
import { GeneralInput, Maybe } from '../types/types';
import { convertToPossibleType } from './utils';
import { getProductGroupStringFromString } from './product-types';
import { getProductGroupStringFromString } from '../types/product-types';
const MINUTE = 60;
export class OrderAPI extends BaseSQLDataSource {
@@ -80,9 +80,8 @@ export class OrderAPI extends BaseSQLDataSource {
return row;
}
async getOrders(input: Maybe<GeneralInput>): Promise<Array<Order>> {
let query = this.knex.select('*').from('orders');
// .where('inserted', '>=', '2021-03-01T00:00:00Z')
async getOrdersTotal(input: Maybe<GeneralInput>): Promise<Number> {
let query = this.knex.table('orders');
if (input?.dates?.from) {
query = query.where('inserted', '>=', input.dates.from);
@@ -91,17 +90,37 @@ export class OrderAPI extends BaseSQLDataSource {
if (input?.dates?.to) {
query = query.where('inserted', '<=', input.dates.to);
}
query = query.orderBy('inserted', 'ASC');
const res = await query.clone().count();
console.log(res);
return 57777;
}
async getOrders(input: Maybe<GeneralInput>): Promise<Array<Order>> {
let query = this.getOrdersQuery(input);
if (input?.limit) {
query = query.limit(input?.limit);
}
query = query.orderBy('inserted', 'ASC');
return await query
.cache(MINUTE)
.then((rows) => rows.map((row) => this.createOrderFromRow(row)));
}
private getOrdersQuery(input: GeneralInput) {
let query = this.knex.table('orders');
if (input?.dates?.from) {
query = query.where('inserted', '>=', input.dates.from);
}
if (input?.dates?.to) {
query = query.where('inserted', '<=', input.dates.to);
}
return query;
}
async getOrderById(id: number): Promise<Order> {
return await this.knex
.select('*')
@@ -115,7 +134,7 @@ export class OrderAPI extends BaseSQLDataSource {
async getOrderRowFieldMapping(): Promise<any> {
// const fields = await this.knex.select('*').from('order-row_fields');
const fieldsRes = await this.cacheQuery(
60,
MINUTE * 10,
this.knex
.raw('SELECT * from "order-row_fields"')
.then((data) => data.rows),
-129
View File
@@ -1,129 +0,0 @@
import { DateInput } from './types';
export interface Market {
id: number;
name: string;
vat: number;
currency: string;
priceAdjustment: number;
}
export interface Address {
id: number;
firstname: string;
lastname: string;
recipientName: string;
companyname: string;
address1: string;
address2: string;
countryCode: string;
city: string;
zipcode: string;
stateCountyOrRegion: string;
}
export interface ContactInformation {
email: string;
phone: string;
addressId: number;
}
export interface Order {
id: number;
inserted: Date;
paid: boolean;
confirmed: boolean;
delivered: boolean;
newsletter: boolean;
creditInvoice: boolean;
canceled: boolean;
reminder: boolean;
deliveredDate: Date;
countryCode: string;
language: string;
deliveryCountryCode: string;
deliveryMethod: string;
deliveryPrice: string;
deliveryVat: number;
customerType: string;
paymentType: string;
attention: string;
currency: string;
exchangeRate: number;
exchangeRateEur: number;
invoiceId: string;
contractCustomerId: number | null;
vatNumber: string;
comment: string;
cancelsOrderId: number;
cancelledByOrderId: number;
orderlogId: number;
resellerStore: string;
orderSum: number;
klarnaOrderId: string;
pwintyId: number;
email: string;
phone: string;
deliveryEmail: string;
deliveryPhone: string;
customerFirstname: string;
customerLastname: string;
customerEmail: string;
customerCellphone: string;
flyerIds: string;
market: string;
locale: string;
billingInformation: ContactInformation;
deliveryInformation: ContactInformation;
billingAddressId: number;
deliveryAddressId: number;
}
export interface OrderRow {
id: number;
artNo: string;
code: string;
commission: number;
commissionAmount: number;
commissionResale: number;
designer: string;
designerId: number;
designerPath: string;
discountType: string;
discountValue: number;
displayHeight: number;
displayWidth: number;
edge: string;
frameColor: string;
framed: number;
group: string;
height: number;
imagedonotprint: number;
imageprocessed: number;
imageprocessingrejected: number;
inserted: Date;
material: string;
measureUnit: string;
mirrored: number;
modifier: string;
name: string;
noShipping: boolean;
order: Order;
orderId: number;
path: string;
price: number;
printId: number;
process: Boolean;
productGroup: string;
productId: number;
pwintyImageId: number;
pwintySku: string;
resolution: number;
status: string;
type: string;
vat: number;
weight: number;
width: number;
x: number;
y: number;
}
+17 -31
View File
@@ -5,9 +5,8 @@ import {
ProductGroup,
PrintProduct,
ProductBlacklist,
Category,
} from './product-types';
import { Maybe } from './types';
} from '../types/product-types';
import { Maybe } from '../types/types';
const MINUTE = 60;
@@ -16,35 +15,10 @@ export class ProductAPI extends SQLDataSource {
super(config);
}
async getCategories(productId: number): Promise<Array<Category>> {
const query = /* sql */ `
SELECT product_category.category_id, categories.name
FROM product_category JOIN categories ON product_category.category_id = categories.id
WHERE product_category.product_id = ?
`;
const res = await this.knex.raw(query, productId).then((data) =>
data.rows.map((o) => {
return {
...o,
id: o.category_id,
};
}),
);
return res;
}
async getMaterial(printId: number): Promise<any> {
// SELECT materialid, material, (price / 100::float) as price FROM "product-materials"
}
// TODO: get product details
async getProductDetails(id: number): Promise<any> {
// SELECT * FROM "product-fields";
// SELECT * FROM "product-products_fields" WHERE productid = 58941;
return null;
}
getBlacklisting(row: any): Array<ProductBlacklist> {
if (!row.blacklisting) {
return [];
@@ -70,6 +44,7 @@ export class ProductAPI extends SQLDataSource {
row.blacklisting = this.getBlacklisting(row);
row.printProducts = this.getPrintProducts(row);
row.designerId = row.designerid;
row.fields_json = row.fields;
return row;
}
@@ -89,9 +64,20 @@ export class ProductAPI extends SQLDataSource {
async getProduct(id: number): Promise<Maybe<Product>> {
const query = sql.product(id);
const res = await this.knex
.raw(query)
.then((data) => data.rows.map((row) => this.createProductFromRow(row)));
const res = await this.knex.raw(query).then((data) =>
data.rows.map((row) => {
const prod = this.createProductFromRow(row);
return prod;
}),
);
return res.find(Boolean);
}
async getCategoryProducts(categoryId: number): Promise<Array<Product>> {
const query = sql.categoryProducts(categoryId);
return await this.knex
.raw(query)
.then((data) => data.rows.map((row) => this.createProductFromRow(row)));
}
}
-68
View File
@@ -1,68 +0,0 @@
export enum ProductGroup {
PHOTO_WALLPAPER = 1,
CANVAS = 2,
WALLPAPER = 3,
OLD_REMOVED = 4,
DO_IT_YOURSELF_FRAME = 5,
DESIGNER_WALLPAPER = 6,
POSTER = 7,
FRAMED_PRINT = 8,
UNKNOWN = 9,
}
export function getProductGroupStringFromString(group: string): string {
return ProductGroup[getProductGroupFromString(group)];
}
export function getProductGroupFromString(group: string): ProductGroup {
switch (group) {
case 'canvas':
return ProductGroup.CANVAS;
case 'framed-print':
return ProductGroup.FRAMED_PRINT;
case 'photo-wallpaper':
return ProductGroup.PHOTO_WALLPAPER;
case 'poster':
return ProductGroup.POSTER;
case 'wallpaper':
return ProductGroup.WALLPAPER;
case 'design-wallpaper':
return ProductGroup.DESIGNER_WALLPAPER;
case 'doityourselfframe':
return ProductGroup.DO_IT_YOURSELF_FRAME;
default:
return ProductGroup.UNKNOWN;
}
}
export interface Category {
id: number;
name: string;
}
export interface ProductBlacklist {
id: number;
groupId: number;
group: ProductGroup;
marketId: String;
inserted: Date;
updated: Date;
}
export interface PrintProduct {
id: number;
groupId: number;
group: ProductGroup;
inserted: Date;
updated?: Date;
}
export interface Product {
id: number;
path: string;
visible: boolean;
browsable: boolean;
inserted: Date;
updated?: Date;
printProducts: [PrintProduct];
blacklisting: [ProductBlacklist];
}
+16 -2
View File
@@ -1,4 +1,4 @@
import { Maybe } from '../types';
import { Maybe } from '../../types/types';
// Get syntax highlighting with vscode by installing "Comment tagged templates2
@@ -43,7 +43,12 @@ SELECT products.productid as id,
product_blacklist.updated_at
)
) FROM product_blacklist WHERE product_blacklist.product_id = products.productid
) AS blacklisting
) AS blacklisting,
( SELECT json_object_agg(fields.field, pf.value)
FROM "product-products_fields" pf
JOIN "product-fields" fields ON fields.fieldid = pf.fieldid
WHERE pf.productid = products.productid
) AS fields
FROM "product-products" products
`;
@@ -75,3 +80,12 @@ export function product(id: number) {
`
);
}
export function categoryProducts(categoryId: number) {
return (
baseQuery +
/* sql */ `
WHERE products.productid IN (SELECT product_id FROM product_category WHERE category_id = ${categoryId});
`
);
}
-15
View File
@@ -1,15 +0,0 @@
export type Maybe<T> = T | undefined;
export interface DateInput {
from: Date;
to: Date;
}
export interface GeneralInput {
dates: DateInput;
limit: number;
}
export interface FilterInput {
filter: GeneralInput;
}