From 491faeabc0714d75ac63429ebb0bbe23df1685a2 Mon Sep 17 00:00:00 2001 From: Simon Dupree Date: Mon, 15 Jul 2024 14:13:15 +0200 Subject: [PATCH 1/2] setup single get product endpoint --- web/database/variants/variants.js | 62 +++++++++++++------ .../products/controllers/get-product.js | 44 +++++++++++++ .../products/controllers/get-products.js | 2 +- .../products/controllers/shopify/products.js | 52 +++------------- web/fdc-modules/products/index.js | 2 + 5 files changed, 97 insertions(+), 65 deletions(-) create mode 100644 web/fdc-modules/products/controllers/get-product.js diff --git a/web/database/variants/variants.js b/web/database/variants/variants.js index 522a5f2..30814cf 100644 --- a/web/database/variants/variants.js +++ b/web/database/variants/variants.js @@ -1,40 +1,62 @@ import { query } from '../connect.js'; async function getVariants() { - return (await query(`SELECT * FROM fdc_variants order by product_id`)).rows + return (await query(`SELECT * FROM fdc_variants order by product_id`)).rows; +} + +async function getVariantsByProductId(productId) { + return ( + await query(`SELECT * FROM fdc_variants where product_id = $1`, [productId]) + ).rows; } async function variantCount() { - return Number((await query(`SELECT count(*) FROM fdc_variants`)).rows[0].count); + return Number( + (await query(`SELECT count(*) FROM fdc_variants`)).rows[0].count + ); } async function getPagedVariants(lastId, limit) { - return (await query(`SELECT * FROM fdc_variants where product_id > $1 order by product_id limit $2`, [lastId, limit])).rows + return ( + await query( + `SELECT * FROM fdc_variants where product_id > $1 order by product_id limit $2`, + [lastId, limit] + ) + ).rows; } function indexedByProductId(variants) { - return variants.reduce((accumulator, row) => { - const productId = row.productId; - return { - ...accumulator, - [productId]: accumulator[productId] ? [...accumulator[productId], row] : [row] - }; - }, {}); + return variants.reduce((accumulator, row) => { + const productId = row.productId; + return { + ...accumulator, + [productId]: accumulator[productId] + ? [...accumulator[productId], row] + : [row] + }; + }, {}); } async function getAndAddVariantsToProducts(products) { - return addVariantsToProducts(products, indexedByProductId(await getVariants())) + return addVariantsToProducts( + products, + indexedByProductId(await getVariants()) + ); } -function addVariantsToProducts(products, variantsByProductId){ - return products.map(product => ({ ...product, fdcVariants: variantsByProductId[product.id] || [] })) +function addVariantsToProducts(products, variantsByProductId) { + return products.map((product) => ({ + ...product, + fdcVariants: variantsByProductId[product.id] || [] + })); } export { - getVariants, - getPagedVariants, - indexedByProductId, - variantCount, - getAndAddVariantsToProducts, - addVariantsToProducts -} \ No newline at end of file + getVariants, + getVariantsByProductId, + getPagedVariants, + indexedByProductId, + variantCount, + getAndAddVariantsToProducts, + addVariantsToProducts +}; diff --git a/web/fdc-modules/products/controllers/get-product.js b/web/fdc-modules/products/controllers/get-product.js new file mode 100644 index 0000000..143a0e6 --- /dev/null +++ b/web/fdc-modules/products/controllers/get-product.js @@ -0,0 +1,44 @@ +import shopify from '../../../shopify.js'; +import getSession from '../../../utils/getShopifySession.js'; +import { createDFCProductsFromShopify } from '../dfc/dfc-products.js'; +import { + findFDCProducts, + getFdcVariantsByProductIdFromDB +} from './shopify/products.js'; + +const getProducts = async (req, res) => { + try { + const { EnterpriseName, ProductId } = req.params; + + const session = await getSession(`${EnterpriseName}.myshopify.com`); + + if (!session) { + return res.status(401).json({ message: 'Unauthorised' }); + } + + const client = new shopify.api.clients.Graphql({ session }); + + const fdcVariantsFromDB = await getFdcVariantsByProductIdFromDB(ProductId); + + if (Object.keys(fdcVariantsFromDB).length === 0) { + return res.status(200).json('No product found'); + } + + const fdcProduct = await findFDCProducts( + client, + Object.keys(fdcVariantsFromDB) + ); + + const dfcProducts = await createDFCProductsFromShopify( + fdcProduct, + fdcVariantsFromDB + ); + + return res.status(200).json(dfcProducts); + } catch (error) { + console.error('Unable to load products', error); + throw new Error(error); + } +}; + +export default getProducts; diff --git a/web/fdc-modules/products/controllers/get-products.js b/web/fdc-modules/products/controllers/get-products.js index 0e86191..ccbd135 100644 --- a/web/fdc-modules/products/controllers/get-products.js +++ b/web/fdc-modules/products/controllers/get-products.js @@ -18,7 +18,7 @@ const getProducts = async (req, res) => { const fdcVariantsFromDB = await getFdcVariantsFromDB(); if (Object.keys(fdcVariantsFromDB).length === 0) { - return res.status(200).json([]); + return res.status(200).json('No products found'); } const fdcProducts = await findFDCProducts( diff --git a/web/fdc-modules/products/controllers/shopify/products.js b/web/fdc-modules/products/controllers/shopify/products.js index 4a4d0ae..ece3fe7 100644 --- a/web/fdc-modules/products/controllers/shopify/products.js +++ b/web/fdc-modules/products/controllers/shopify/products.js @@ -1,6 +1,7 @@ import { getShopifyIdSubstring } from '../../../../database/utils/get-shopify-id-substring.js'; import { getVariants, + getVariantsByProductId, indexedByProductId } from '../../../../database/variants/variants.js'; @@ -20,6 +21,13 @@ export async function getFdcVariantsFromDB() { return mappedVariantsByProductId; } +export async function getFdcVariantsByProductIdFromDB(productId) { + const variants = await getVariantsByProductId(productId); + const mappedVariantsByProductId = indexedByProductId(variants); + + return mappedVariantsByProductId; +} + export async function findProductsByIds(client, ids) { const query = ` query findProducts($ids: [ID!]!) { @@ -71,47 +79,3 @@ export async function findProductsByIds(client, ids) { })) })); } - -export async function findProductById(client, id) { - const query = ` - query findProduct($id: ID!) { - product: node(id: $id) { - ... on Product { - id - tags - title - description - images(first: 10) { - edges { - node { - id - src - } - } - } - variants(first: 250) { - edges { - node { - id - title - } - } - } - } - } - } - `; - const response = await client.query({ - data: { - query, - variables: { id: `gid://shopify/Product/${id}` } - } - }); - - if (response.errors) { - console.error('Failed to load Product', JSON.stringify(response.errors)); - throw new Error('Failed to load Product'); - } - - return response.body.data.product; -} diff --git a/web/fdc-modules/products/index.js b/web/fdc-modules/products/index.js index 6e0b490..184a2e0 100644 --- a/web/fdc-modules/products/index.js +++ b/web/fdc-modules/products/index.js @@ -1,8 +1,10 @@ import { Router } from 'express'; import getProducts from './controllers/get-products.js'; +import getProduct from './controllers/get-product.js'; const fdcProductRoutes = Router({ mergeParams: true }); fdcProductRoutes.get('/', getProducts); +fdcProductRoutes.get('/:ProductId', getProduct); export default fdcProductRoutes; From c66ffe82b79603060d93a1123998d4fe21f52a71 Mon Sep 17 00:00:00 2001 From: Simon Dupree Date: Mon, 15 Jul 2024 14:16:00 +0200 Subject: [PATCH 2/2] update name --- web/fdc-modules/products/controllers/get-product.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/fdc-modules/products/controllers/get-product.js b/web/fdc-modules/products/controllers/get-product.js index 143a0e6..eb8bd0d 100644 --- a/web/fdc-modules/products/controllers/get-product.js +++ b/web/fdc-modules/products/controllers/get-product.js @@ -6,7 +6,7 @@ import { getFdcVariantsByProductIdFromDB } from './shopify/products.js'; -const getProducts = async (req, res) => { +const getProduct = async (req, res) => { try { const { EnterpriseName, ProductId } = req.params; @@ -41,4 +41,4 @@ const getProducts = async (req, res) => { } }; -export default getProducts; +export default getProduct;