diff options
Diffstat (limited to 'src/pages/api')
| -rw-r--r-- | src/pages/api/activation-request.js | 24 | ||||
| -rw-r--r-- | src/pages/api/shop/brands.js | 2 | ||||
| -rw-r--r-- | src/pages/api/shop/finish-checkout.js | 84 | ||||
| -rw-r--r-- | src/pages/api/shop/product-homepage.js | 3 | ||||
| -rw-r--r-- | src/pages/api/shop/promo.js | 204 | ||||
| -rw-r--r-- | src/pages/api/shop/search.js | 57 |
6 files changed, 312 insertions, 62 deletions
diff --git a/src/pages/api/activation-request.js b/src/pages/api/activation-request.js index 64a67bbc..2b8ccec3 100644 --- a/src/pages/api/activation-request.js +++ b/src/pages/api/activation-request.js @@ -1,10 +1,12 @@ -import odooApi from '@/core/api/odooApi' -import mailer from '@/core/utils/mailer' +import odooApi from '@/core/api/odooApi'; +import mailer from '@/core/utils/mailer'; export default async function handler(req, res) { try { - const { email } = req.body - let result = await odooApi('POST', '/api/v1/user/activation-request', { email }) + const { email } = req.body; + let result = await odooApi('POST', '/api/v1/user/activation-request', { + email, + }); if (result.activationRequest) { mailer.sendMail({ from: 'noreply@indoteknik.com', @@ -14,14 +16,14 @@ export default async function handler(req, res) { <h1>Permintaan Aktivasi Akun Indoteknik</h1> <br> <p>Aktivasi akun anda melalui link berikut: <a href="${process.env.NEXT_PUBLIC_SELF_HOST}/activate?token=${result.token}">Aktivasi Akun</a></p> - ` - }) + `, + }); } - delete result.user - delete result.token - res.status(200).json(result) + delete result.user; + delete result.token; + res.status(200).json(result); } catch (error) { - console.log(error) - res.status(400).json({ error: error.message }) + console.log(error); + res.status(400).json({ error: error.message }); } } diff --git a/src/pages/api/shop/brands.js b/src/pages/api/shop/brands.js index cc64a7e7..9c2824b3 100644 --- a/src/pages/api/shop/brands.js +++ b/src/pages/api/shop/brands.js @@ -24,6 +24,8 @@ export default async function handler(req, res) { params = `name_s:${req.query.params}`.toLowerCase(); } } + if(req.query.rows) rows = req.query.rows; + const url = `${SOLR_HOST}/solr/brands/select?q=${params}&q.op=OR&indent=true&rows=${rows}&${sort}`; let brands = await axios(url); let dataBrands = responseMap(brands.data.response.docs); diff --git a/src/pages/api/shop/finish-checkout.js b/src/pages/api/shop/finish-checkout.js index 9eaa36db..4dcc915c 100644 --- a/src/pages/api/shop/finish-checkout.js +++ b/src/pages/api/shop/finish-checkout.js @@ -1,60 +1,66 @@ -import odooApi from '@/core/api/odooApi' -import mailer from '@/core/utils/mailer' -import FinishCheckoutEmail from '@/lib/checkout/email/FinishCheckoutEmail' -import { render } from '@react-email/render' -import axios from 'axios' -import camelcaseObjectDeep from 'camelcase-object-deep' +import odooApi from '@/core/api/odooApi'; +import mailer from '@/core/utils/mailer'; +import FinishCheckoutEmail from '@/lib/checkout/email/FinishCheckoutEmail'; +import { render } from '@react-email/render'; +import axios from 'axios'; +import camelcaseObjectDeep from 'camelcase-object-deep'; export default async function handler(req, res) { - const { orderName = null } = req.query + const { orderName = null } = req.query; if (!orderName) { - return res.status(422).json({ error: 'parameter missing' }) + return res.status(422).json({ error: 'parameter missing' }); } - let { auth } = req.cookies + let { auth } = req.cookies; if (!auth) { - return res.status(401).json({ error: 'Unauthorized' }) + return res.status(401).json({ error: 'Unauthorized' }); } - auth = JSON.parse(auth) + auth = JSON.parse(auth); - const midtransAuthKey = btoa(process.env.MIDTRANS_SERVER_KEY + ':') + const midtransAuthKey = btoa(process.env.MIDTRANS_SERVER_KEY + ':'); const midtransHeaders = { Accept: 'application/json', 'Content-Type': 'application/json', - Authorization: `Basic ${midtransAuthKey}` - } - let midtransStatus = {} + Authorization: `Basic ${midtransAuthKey}`, + }; + let midtransStatus = {}; try { - midtransStatus = await axios.get(`${process.env.MIDTRANS_HOST}/v2/${orderName}/status`, { - headers: midtransHeaders - }) - midtransStatus = camelcaseObjectDeep(midtransStatus.data) + midtransStatus = await axios.get( + `${process.env.MIDTRANS_HOST}/v2/${orderName}/status`, + { + headers: midtransHeaders, + } + ); + midtransStatus = camelcaseObjectDeep(midtransStatus.data); } catch (error) { - console.log(error) + console.log(error); } - let statusPayment = 'manual' + let statusPayment = 'manual'; if (midtransStatus?.orderId) { - const transactionStatus = midtransStatus.transactionStatus - statusPayment = 'failed' + const transactionStatus = midtransStatus.transactionStatus; + statusPayment = 'failed'; if (['capture', 'settlement'].includes(transactionStatus)) { - statusPayment = 'success' + statusPayment = 'success'; } else if (transactionStatus == 'pending') { - statusPayment = 'pending' + statusPayment = 'pending'; } } - const query = `name=${orderName.replaceAll('-', '/')}&limit=1&context=quotation` + const query = `name=${orderName.replaceAll( + '-', + '/' + )}&limit=1&context=quotation`; const searchTransaction = await odooApi( 'GET', `/api/v1/partner/${auth.partnerId}/sale_order?${query}`, {}, { Token: auth.token } - ) + ); if (searchTransaction.saleOrderTotal == 0) { - return res.status(400).json({ error: 'Transaction Not Found' }) + return res.status(400).json({ error: 'Transaction Not Found' }); } let transaction = await odooApi( @@ -62,17 +68,17 @@ export default async function handler(req, res) { `/api/v1/partner/${auth.partnerId}/sale_order/${searchTransaction.saleOrders[0].id}`, {}, { Token: auth.token } - ) + ); if (!transaction?.id) { - return res.status(400).json({ error: 'Transaction Detail Not Found' }) + return res.status(400).json({ error: 'Transaction Detail Not Found' }); } - transaction.subtotal = 0 - transaction.discountTotal = 0 + transaction.subtotal = 0; + transaction.discountTotal = 0; for (const product of transaction.products) { - transaction.subtotal += product.price.price * product.quantity + transaction.subtotal += product.price.price * product.quantity; transaction.discountTotal -= - (product.price.price - product.price.priceDiscount) * product.quantity + (product.price.price - product.price.priceDiscount) * product.quantity; } const emailMessage = render( @@ -81,14 +87,14 @@ export default async function handler(req, res) { payment={midtransStatus} statusPayment={statusPayment} /> - ) + ); mailer.sendMail({ - from: 'sales@indoteknik.com', + from: 'noreply@indoteknik.com', to: transaction.address.customer.email, subject: 'Pembelian di Indoteknik.com', - html: emailMessage - }) + html: emailMessage, + }); - return res.status(200).json({ description: 'success' }) + return res.status(200).json({ description: 'success' }); } diff --git a/src/pages/api/shop/product-homepage.js b/src/pages/api/shop/product-homepage.js index 02c01ee0..61732c77 100644 --- a/src/pages/api/shop/product-homepage.js +++ b/src/pages/api/shop/product-homepage.js @@ -36,7 +36,8 @@ const respoonseMap = (productHomepage, products) => { name: productHomepage.name_s, image: productHomepage.image_s, url: productHomepage.url_s, - products: products + products: products, + categoryIds: productHomepage.category_id_ids, } return productMapped diff --git a/src/pages/api/shop/promo.js b/src/pages/api/shop/promo.js new file mode 100644 index 00000000..f90c8559 --- /dev/null +++ b/src/pages/api/shop/promo.js @@ -0,0 +1,204 @@ +import { productMappingSolr, promoMappingSolr } from '@/utils/solrMapping'; +import axios from 'axios'; +import camelcaseObjectDeep from 'camelcase-object-deep'; + +export default async function handler(req, res) { + const { + q = '*', + page = 1, + brand = '', + category = '', + priceFrom = 0, + priceTo = 0, + orderBy = 'if(exists(sequence_i),0,1) asc, sequence_i asc,', + operation = 'AND', + fq = '', + limit = 30, + } = req.query; + + let { stock = '' } = req.query; + + let paramOrderBy = 'if(exists(sequence_i),0,1) asc, sequence_i asc,'; + switch (orderBy) { + case 'price-asc': + paramOrderBy += 'price_tier1_v2_f ASC'; + break; + case 'price-desc': + paramOrderBy += 'price_tier1_v2_f DESC'; + break; + case 'popular': + paramOrderBy += 'product_rating_f DESC, search_rank_i DESC,'; + break; + case 'popular-weekly': + paramOrderBy += 'search_rank_weekly_i DESC'; + break; + case 'stock': + paramOrderBy += 'product_rating_f DESC, stock_total_f DESC'; + break; + case 'flashsale-price-asc': + paramOrderBy += 'flashsale_price_f ASC'; + break; + default: + paramOrderBy += ''; + break; + } + + let checkQ = q.trim().split(/[\s\+\-\!\(\)\{\}\[\]\^"~\*\?:\\\/]+/); + let newQ = checkQ.length > 1 ? escapeSolrQuery(q) + '*' : escapeSolrQuery(q); + + let offset = (page - 1) * limit; + let parameter = [ + 'facet.field=manufacture_name_s', + 'facet.field=category_name', + 'facet=true', + 'indent=true', + `facet.limit=-1`, + // `facet.query=${escapeSolrQuery(q)}`, + `q.op=${operation}`, + `q=${q}`, + // 'qf=name_s', + `start=${parseInt(offset)}`, + `rows=${limit}`, + `sort=${paramOrderBy}`, + `fq=product_ids:[* TO *]`, + `fq=active_b:true`, + ]; + + if (priceFrom > 0 || priceTo > 0) { + parameter.push( + `fq=price_tier1_v2_f:[${priceFrom == '' ? '*' : priceFrom} TO ${ + priceTo == '' ? '*' : priceTo + }]` + ); + } + + let { auth } = req.cookies; + if (auth) { + auth = JSON.parse(auth); + if (auth.feature.onlyReadyStock) stock = true; + } + + if (brand) + parameter.push( + `fq=${brand + .split(',') + .map( + (manufacturer) => + `manufacture_name_s:"${encodeURIComponent(manufacturer)}"` + ) + .join(' OR ')}` + ); + if (category) + parameter.push( + `fq=${category + .split(',') + .map((cat) => `category_name:"${encodeURIComponent(cat)}"`) + .join(' OR ')}` + ); + // if (category) parameter.push(`fq=category_name:${capitalizeFirstLetter(category.replace(/,/g, ' OR '))}`) + if (stock) parameter.push(`fq=stock_total_f:{1 TO *}`); + + // Single fq in url params + if (typeof fq === 'string') parameter.push(`fq=${fq}`); + // Multi fq in url params + if (Array.isArray(fq)) + parameter = parameter.concat(fq.map((val) => `fq=${val}`)); + + let result = await axios( + process.env.SOLR_HOST + '/solr/promotion_program_lines/select?' + parameter.join('&') + ); + try { + result.data.response.products = promoMappingSolr( + result.data.response.docs + ); + + result.data.responseHeader.params.start = parseInt( + result.data.responseHeader.params.start + ); + result.data.responseHeader.params.rows = parseInt( + result.data.responseHeader.params.rows + ); + delete result.data.response.docs; + // result.data = camelcaseObjectDeep(result.data); + result.data = result.data; + res.status(200).json(result.data); + } catch (error) { + res.status(400).json({ error: error.message }); + } +} + +const escapeSolrQuery = (query) => { + if (query == '*') return query; + + query = query.replace(/-/g, ' '); + + const specialChars = /([\+\!\(\)\{\}\[\]\^"~\*\?:\\\/])/g; + const words = query.split(/\s+/); + const escapedWords = words.map((word) => { + if (specialChars.test(word)) { + return word.replace(specialChars, '\\$1'); + } + return word; + }); + + return escapedWords.join(' '); +}; + + +/*const productResponseMap = (products, pricelist) => { + return products.map((product) => { + let price = product.price_tier1_v2_f || 0 + let priceDiscount = product.price_discount_f || 0 + let discountPercentage = product.discount_f || 0 + + if (pricelist) { + // const pricelistDiscount = product?.[`price_${pricelist}_f`] || false + // const pricelistDiscountPerc = product?.[`discount_${pricelist}_f`] || false + + // if (pricelistDiscount && pricelistDiscount > 0) priceDiscount = pricelistDiscount + // if (pricelistDiscountPerc && pricelistDiscountPerc > 0) + // discountPercentage = pricelistDiscountPerc + + price = product?.[`price_${pricelist}_f`] || 0 + } + + if (product?.flashsale_id_i > 0) { + price = product?.flashsale_base_price_f || 0 + priceDiscount = product?.flashsale_price_f || 0 + discountPercentage = product?.flashsale_discount_f || 0 + } + + let productMapped = { + id: product.product_id_i || '', + image: product.image_s || '', + code: product.default_code_s || '', + name: product.name_s || '', + lowestPrice: { price, priceDiscount, discountPercentage }, + variantTotal: product.variant_total_i || 0, + stockTotal: product.stock_total_f || 0, + weight: product.weight_f || 0, + manufacture: {}, + categories: [], + flashSale: { + id: product?.flashsale_id_i, + name: product?.product?.flashsale_name_s, + tag : product?.flashsale_tag_s || 'FLASH SALE' + } + } + + if (product.manufacture_id_i && product.manufacture_name_s) { + productMapped.manufacture = { + id: product.manufacture_id_i || '', + name: product.manufacture_name_s || '' + } + } + + productMapped.categories = [ + { + id: product.category_id_i || '', + name: product.category_name_s || '' + } + ] + return productMapped + }) +}*/ diff --git a/src/pages/api/shop/search.js b/src/pages/api/shop/search.js index 6f98efcb..6269d3ed 100644 --- a/src/pages/api/shop/search.js +++ b/src/pages/api/shop/search.js @@ -1,6 +1,8 @@ import { productMappingSolr } from '@/utils/solrMapping'; import axios from 'axios'; import camelcaseObjectDeep from 'camelcase-object-deep'; +import searchSuggestApi from '@/core/api/searchSuggestApi'; +import { ECDH } from 'crypto'; export default async function handler(req, res) { const { @@ -14,6 +16,7 @@ export default async function handler(req, res) { operation = 'AND', fq = '', limit = 30, + source = '', } = req.query; let { stock = '' } = req.query; @@ -42,10 +45,40 @@ export default async function handler(req, res) { paramOrderBy += ''; break; } - + + // let suggestWord = null; + // let keywords = q; + // let checkQ = null; + + // if (q != '*') { + // checkQ = q.trim().split(/[\s\+\-\!\(\)\{\}\[\]\^"~\*\?:\\\/]+/); + // if (checkQ.length > 1) { + // const dataSearchSuggest = await axios( + // `${process.env.NEXT_PUBLIC_SELF_HOST}/api/shop/suggest?q=${checkQ[1]}` + // ); + // suggestWord = dataSearchSuggest.data.suggestions[0]; + // } + // if (suggestWord && suggestWord?.term.split(' ').length <= 1) { + // keywords = `"${escapeSolrQuery(checkQ[0] + ' ' + suggestWord?.term)}"`; + // } + // } + + // let newQ = keywords; + let checkQ = q.trim().split(/[\s\+\-\!\(\)\{\}\[\]\^"~\*\?:\\\/]+/); - let newQ = checkQ.length > 1 ? escapeSolrQuery(q) + '*' : escapeSolrQuery(q); + let newQ = escapeSolrQuery(q); + + const formattedQuery = `(${newQ.split(' ').map(term => `${term}*`).join(' ') })`; + const mm = checkQ.length > 2 ? checkQ.length > 5 ? '55%' : '85%' : `${checkQ.length}`; + + const filterQueries = [ + '-publish_b:false', + 'product_rating_f:[8 TO *]', + 'price_tier1_v2_f:[1 TO *]' + ]; + const fq_ = filterQueries.join('AND '); + let offset = (page - 1) * limit; let parameter = [ 'facet.field=manufacture_name_s', @@ -53,13 +86,15 @@ export default async function handler(req, res) { 'facet=true', 'indent=true', `facet.query=${escapeSolrQuery(q)}`, - `q.op=${operation}`, - `q=${newQ}`, - 'qf=name_s', + `q.op=OR`, + `q=${source == 'similar' || checkQ.length < 3 ? checkQ.length < 2 ? newQ : newQ + '*' : formattedQuery }`, + `defType=edismax`, + 'qf=name_s description_clean_t category_name manufacture_name_s variants_code_t variants_name_t category_id_ids default_code_s', `start=${parseInt(offset)}`, `rows=${limit}`, `sort=${paramOrderBy}`, - `fq=-publish_b:false, product_rating_f:[8 TO *], price_tier1_v2_f:[1 TO *]`, + `fq=${encodeURIComponent(fq_)}`, + `mm=${encodeURIComponent(mm)}`, ]; if (priceFrom > 0 || priceTo > 0) { @@ -97,14 +132,15 @@ export default async function handler(req, res) { if (stock) parameter.push(`fq=stock_total_f:{1 TO *}`); // Single fq in url params - if (typeof fq === 'string') parameter.push(`fq=${fq}`); + if (typeof fq === 'string') parameter.push(`fq=${encodeURIComponent(fq)}`); // Multi fq in url params if (Array.isArray(fq)) - parameter = parameter.concat(fq.map((val) => `fq=${val}`)); - + parameter = parameter.concat(fq.map((val) => `fq=${encodeURIComponent(val)}`)); + let result = await axios( process.env.SOLR_HOST + '/solr/product/select?' + parameter.join('&') ); + try { result.data.response.products = productMappingSolr( result.data.response.docs, @@ -126,7 +162,7 @@ export default async function handler(req, res) { const escapeSolrQuery = (query) => { if (query == '*') return query; - + query = query.replace(/-/g, ' '); const specialChars = /([\+\!\(\)\{\}\[\]\^"~\*\?:\\\/])/g; @@ -141,7 +177,6 @@ const escapeSolrQuery = (query) => { return escapedWords.join(' '); }; - /*const productResponseMap = (products, pricelist) => { return products.map((product) => { let price = product.price_tier1_v2_f || 0 |
