From 07edeea667e6eb7170493c7ea7e985b561d61750 Mon Sep 17 00:00:00 2001 From: shreyvishal Date: Mon, 8 Apr 2024 15:16:19 +0530 Subject: [PATCH] Added: Update Status API --- .env.sample | 5 +- .github/workflows/api_tests.yml | 3 + .github/workflows/deploy.yml | 3 + .github/workflows/lint_checks.yml | 4 +- .github/workflows/unit_tests.yml | 4 +- controllers/Bot.js | 4 +- controllers/ControlCenter.js | 77 ++++++++++++++++++- server.js | 5 +- services/Actions.js | 8 +- services/CronService.js | 76 +++++++++++++++++++ services/DBService.js | 32 ++++++++ utils/constants.js | 121 +++++++++++++++++++++++++++++- 12 files changed, 328 insertions(+), 14 deletions(-) create mode 100644 services/CronService.js diff --git a/.env.sample b/.env.sample index 3df3238..d6fef76 100644 --- a/.env.sample +++ b/.env.sample @@ -10,4 +10,7 @@ TEST_RECEPIENT_NUMBER= STRAPI_TOURISM_TOKEN= GOOGLE_MAPS_API_KEY=your_api_key_here SERVER_URL=http://13.201.62.138:3001 -DEVELOPER_MODE_ON=0 \ No newline at end of file +DEVELOPER_MODE_ON=0 +STRAPI_RETAIL_TOKEN= +STRAPI_ENERGY_TOKEN= +STRAPI_HOTEL_TOKEN= diff --git a/.github/workflows/api_tests.yml b/.github/workflows/api_tests.yml index fd84fed..0e0110e 100644 --- a/.github/workflows/api_tests.yml +++ b/.github/workflows/api_tests.yml @@ -27,6 +27,9 @@ jobs: echo "GOOGLE_MAPS_API_KEY=${{secrets.GOOGLE_MAPS_API_KEY}}" >> .env echo "SERVER_URL=${{secrets.SERVER_URL}}" >> .env echo "DEVELOPER_MODE_ON=${{secrets.DEVELOPER_MODE_ON}}" >> .env + echo "STRAPI_RETAIL_TOKEN=${{secrets.STRAPI_RETAIL_TOKEN}}" >> .env + echo "STRAPI_ENERGY_TOKEN=${{secrets.STRAPI_ENERGY_TOKEN}}" >> .env + echo "STRAPI_HOTEL_TOKEN=${{secrets.STRAPI_HOTEL_TOKEN}}" >> .env - name: Set up Node.js uses: actions/setup-node@v2 diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index d4fcde1..93e34ce 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -28,6 +28,9 @@ jobs: echo "GOOGLE_MAPS_API_KEY=${{secrets.GOOGLE_MAPS_API_KEY}}" >> .env echo "SERVER_URL=${{secrets.SERVER_URL}}" >> .env echo "DEVELOPER_MODE_ON=${{secrets.DEVELOPER_MODE_ON}}" >> .env + echo "STRAPI_RETAIL_TOKEN=${{secrets.STRAPI_RETAIL_TOKEN}}" >> .env + echo "STRAPI_ENERGY_TOKEN=${{secrets.STRAPI_ENERGY_TOKEN}}" >> .env + echo "STRAPI_HOTEL_TOKEN=${{secrets.STRAPI_HOTEL_TOKEN}}" >> .env - name: Create SSH key file run: echo -e "${{ secrets.EC2_SSH_KEY }}" > ~/ec2_key diff --git a/.github/workflows/lint_checks.yml b/.github/workflows/lint_checks.yml index 34e1db1..7f9972f 100644 --- a/.github/workflows/lint_checks.yml +++ b/.github/workflows/lint_checks.yml @@ -27,7 +27,9 @@ jobs: echo "GOOGLE_MAPS_API_KEY=${{secrets.GOOGLE_MAPS_API_KEY}}" >> .env echo "SERVER_URL=${{secrets.SERVER_URL}}" >> .env echo "DEVELOPER_MODE_ON=${{secrets.DEVELOPER_MODE_ON}}" >> .env - + echo "STRAPI_RETAIL_TOKEN=${{secrets.STRAPI_RETAIL_TOKEN}}" >> .env + echo "STRAPI_ENERGY_TOKEN=${{secrets.STRAPI_ENERGY_TOKEN}}" >> .env + echo "STRAPI_HOTEL_TOKEN=${{secrets.STRAPI_HOTEL_TOKEN}}" >> .env - name: Set up Node.js uses: actions/setup-node@v2 with: diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml index 1e426fe..1e09e10 100644 --- a/.github/workflows/unit_tests.yml +++ b/.github/workflows/unit_tests.yml @@ -27,7 +27,9 @@ jobs: echo "GOOGLE_MAPS_API_KEY=${{secrets.GOOGLE_MAPS_API_KEY}}" >> .env echo "SERVER_URL=${{secrets.SERVER_URL}}" >> .env echo "DEVELOPER_MODE_ON=${{secrets.DEVELOPER_MODE_ON}}" >> .env - + echo "STRAPI_RETAIL_TOKEN=${{secrets.STRAPI_RETAIL_TOKEN}}" >> .env + echo "STRAPI_ENERGY_TOKEN=${{secrets.STRAPI_ENERGY_TOKEN}}" >> .env + echo "STRAPI_HOTEL_TOKEN=${{secrets.STRAPI_HOTEL_TOKEN}}" >> .env - name: Set up Node.js uses: actions/setup-node@v2 with: diff --git a/controllers/Bot.js b/controllers/Bot.js index 82f0474..c862c47 100644 --- a/controllers/Bot.js +++ b/controllers/Bot.js @@ -7,6 +7,8 @@ import MapsService from '../services/MapService.js' import get_text_by_key from '../utils/language.js' const mapService = new MapsService() +import {ORDER_DETAILS} from '../utils/constants.js' +import CronService from '../services/CronService.js' const actionsService = new ActionsService() const db = new DBService(); @@ -385,5 +387,5 @@ async function process_action(action, text, session, sender=null, format='applic } export default { process_wa_webhook, - process_text + process_text, } diff --git a/controllers/ControlCenter.js b/controllers/ControlCenter.js index 431047b..53b72ad 100644 --- a/controllers/ControlCenter.js +++ b/controllers/ControlCenter.js @@ -7,7 +7,12 @@ import { NEW_CATALOG_AVAILABLE, TRIGGER_BLIZZARD_MESSAGE, CANCEL_BOOKING_MESSAGE, - TOURISM_STRAPI_URL + TOURISM_STRAPI_URL, + HOTEL_STRAPI_URL, + RETAIL_STRAPI_URL, + ENERGY_STRAPI_URL, + DOMAINS, + UPDATE_STATUS_MESSAGE } from '../utils/constants.js' import DBService from '../services/DBService.js' import MapsService from '../services/MapService.js' @@ -138,4 +143,72 @@ export const notify = async (req, res) => { res.send("Triggered!") } else res.status(400).send('Point and message are required in the body.') - } \ No newline at end of file + } + + +export const updateStatus = async (req, res) => { + try { + const { orderId, domain="" } = req.body + if(!orderId){ + return res.status(400).json({message:"Order Id is Required", status:false}) + } + let DOMAIN_DETAILS = { + url:"", + token:"", + message:"" + } + switch(domain){ + case DOMAINS.ENERGY: + DOMAIN_DETAILS = { + url:ENERGY_STRAPI_URL, + token:process.env.STRAPI_ENERGY_TOKEN, + message:UPDATE_STATUS_MESSAGE.ENERGY + + } + break; + case DOMAINS.RETAIL: + DOMAIN_DETAILS = { + url:RETAIL_STRAPI_URL, + token:process.env.STRAPI_RETAIL_TOKEN, + message:UPDATE_STATUS_MESSAGE.RETAIL + } + break; + case DOMAINS.HOTEL: + DOMAIN_DETAILS = { + url:HOTEL_STRAPI_URL, + token:process.env.STRAPI_HOTEL_TOKEN, + message:UPDATE_STATUS_MESSAGE.HOTEL + } + break; + case DOMAINS.TOURISM: + DOMAIN_DETAILS = { + url:TOURISM_STRAPI_URL, + token:process.env.STRAPI_TOURISM_TOKEN, + message:UPDATE_STATUS_MESSAGE.TOURISM + } + break; + } + const validOrderId = await action.call_api(`${DOMAIN_DETAILS.url}/orders/${orderId}`,'GET',{},{ Authorization: `Bearer ${DOMAIN_DETAILS.token}`}) + logger.info(`OrderDetails: ${JSON.stringify(validOrderId)}`) + if(!validOrderId.status){ + return res.status(400).send({ message: `Invalid Order Id`, status:false }) + } + + const getOrderFulfillmentDetails = await action.call_api(`${DOMAIN_DETAILS.url}/order-fulfillments?order_id=${orderId}`,'GET',{},{ Authorization: `Bearer ${DOMAIN_DETAILS.token}`}) + logger.info(`Order Fulfillment Details: ${JSON.stringify(getOrderFulfillmentDetails)}`) + if (getOrderFulfillmentDetails.data.data.length) { + const updateStatusResponse = await action.call_api(`${DOMAIN_DETAILS.url}/order-fulfillments/${getOrderFulfillmentDetails.data.data[0].id}`,'PUT',{ + data: { + state_code: DOMAIN_DETAILS.message, + state_value: DOMAIN_DETAILS.message, + }, + },{ Authorization: `Bearer ${DOMAIN_DETAILS.token}`}) + return res.status(200).send({ message: `Status Updated to: ${updateStatusResponse.data.data.attributes.state_value}`, status:true }) + } + + return res.status(400).send({ message: 'Order Status Update Failed', status:false }) + } catch (error) { + logger.error(error.message) + return res.status(400).send({ message: error.message, status:false }) + } +} diff --git a/server.js b/server.js index 18ce7f5..be8f7f4 100644 --- a/server.js +++ b/server.js @@ -6,11 +6,13 @@ import bodyParser from 'body-parser' import logger from './utils/logger.js' import messageController from './controllers/Bot.js' import DBService from './services/DBService.js' + import { cancelBooking, updateCatalog, notify, - triggerExceptionOnLocation + triggerExceptionOnLocation, + updateStatus } from './controllers/ControlCenter.js' import path from 'path' import { fileURLToPath } from 'url'; @@ -30,6 +32,7 @@ app.post('/notify', notify) app.post('/cancel-booking', cancelBooking) app.post('/update-catalog', updateCatalog) app.post('/trigger-exception', triggerExceptionOnLocation) +app.post('/update-status', updateStatus) // Reset all sessions const db = new DBService() diff --git a/services/Actions.js b/services/Actions.js index 84b7315..a08a202 100644 --- a/services/Actions.js +++ b/services/Actions.js @@ -24,8 +24,8 @@ class Actions { } async call_api(endpoint, method, data, headers = {}) { - logger.info(`Calling ${method} on ${endpoint}...`); - logger.info(`Data: ${JSON.stringify(data, null, 2)}`); + // logger.info(`Calling ${method} on ${endpoint}...`); + // logger.info(`Data: ${JSON.stringify(data, null, 2)}`); let responseObject = { status: false, retry: false, @@ -50,8 +50,8 @@ class Actions { data: response.data, cookies: response.headers['set-cookie'], } - logger.info(`API call was successful: , response.status`) - logger.info(JSON.stringify(response.data, null, 2)) + // logger.info(`API call was successful: , response.status`) + // logger.info(JSON.stringify(response.data, null, 2)) } catch (error) { logger.error(error) diff --git a/services/CronService.js b/services/CronService.js new file mode 100644 index 0000000..fc5ea9e --- /dev/null +++ b/services/CronService.js @@ -0,0 +1,76 @@ +import { + TOURISM_STRAPI_URL, + HOTEL_STRAPI_URL, + RETAIL_STRAPI_URL, + ENERGY_STRAPI_URL, + DOMAINS +} from '../utils/constants.js' +import ActionsService from '../services/Actions.js' +const action = new ActionsService() +class CronService { + constructor() { + + } + async sendStatusUpdatedNotification(db, recipient){ + try{ + const data = await db.get_data('orderDetails') + if(data.data.domain){ + const statusNotificationPromises = []; + for(let i=0;istrapiOrders.id == order.orderId) + console.log("here-->",validOrderFulfillment.length, validOrderFulfillment[0].attributes.state_code !== null, order.orderFulfillmentStatus, validOrderFulfillment[0].attributes.state_code ,validOrderFulfillment[0].attributes.state_code !== order.orderFulfillmentStatus); + if(validOrderFulfillment.length && validOrderFulfillment[0].attributes.state_code && validOrderFulfillment[0].attributes.state_code !== order.orderFulfillmentStatus){ + console.log("here"); + await action.send_message( + process.env.TEST_RECEPIENT_NUMBER, + `Hey,\nStatus for order id: ${order.orderId} for Domain: ${domainName} is changed.\nNew Status Is ${validOrderFulfillment[0].attributes.state_code}` + ) + } + } + } + return {} + } + }catch(error){ + console.log(error) + throw new Error(error.message) + } + + } +} + +export default CronService \ No newline at end of file diff --git a/services/DBService.js b/services/DBService.js index b364c26..47eabfb 100644 --- a/services/DBService.js +++ b/services/DBService.js @@ -149,6 +149,38 @@ class DBService { return sessions; } + async set_data(key, data) { + let response = { + status: false, + } + try { + await this.redisClient.set(key, JSON.stringify(data)) + response.status = true + response.message = 'Data set successfully!' + } catch (err) { + logger.error(err) + response.error = err + } + + logger.info(response) + return response + } + async get_data(key) { + let response = { + status: false, + } + try { + const data = await this.redisClient.get(key) + response.status = true + response.message = 'Data set successfully!'; + response.data = JSON.parse(data) + } catch (err) { + logger.error(err) + response.error = err + } + + logger.info(response) + return response} } export default DBService; \ No newline at end of file diff --git a/utils/constants.js b/utils/constants.js index 9d4f394..9d66b47 100644 --- a/utils/constants.js +++ b/utils/constants.js @@ -2,7 +2,122 @@ export const ITEM_ID = '4' export const ITEM_NAME = 'Ticket Pass-Mueseum' export const CAT_ATTR_TAG_RELATIONS = [2, 3, 4, 5] -export const TRIGGER_BLIZZARD_MESSAGE = "Hey, Triggering a Blizzard"; -export const CANCEL_BOOKING_MESSAGE = `Dear Guest,\n\nApologies, but your hotel booking with us has been canceled due to unforeseen circumstances. \nWe understand the inconvenience and are here to assist you with any alternative arrangements needed. \n\nPlease contact us for further assistance.`; +export const TRIGGER_BLIZZARD_MESSAGE = 'Hey, Triggering a Blizzard' +export const CANCEL_BOOKING_MESSAGE = `Dear Guest,\n\nApologies, but your hotel booking with us has been canceled due to unforeseen circumstances. \nWe understand the inconvenience and are here to assist you with any alternative arrangements needed. \n\nPlease contact us for further assistance.` export const NEW_CATALOG_AVAILABLE = `Dear Guest,\n\n Checkout this new place to visit.` -export const TOURISM_STRAPI_URL = "https://mit-bpp-tourism.becknprotocol.io/api" +export const TOURISM_STRAPI_URL = 'https://mit-bpp-tourism.becknprotocol.io/api' +export const HOTEL_STRAPI_URL = 'https://mit-bpp-hotel.becknprotocol.io/api' +export const ENERGY_STRAPI_URL = 'https://mit-bpp-energy.becknprotocol.io/api' +export const RETAIL_STRAPI_URL = 'https://mit-bpp-retail.becknprotocol.io/api' +export const DOMAINS = { + RETAIL: 'retail', + HOTEL: 'hotel', + ENERGY: 'energy', + TOURISM: 'tourism', +} +export const UPDATE_STATUS_MESSAGE = { + RETAIL: 'order-picked-up', + HOTEL: 'checkn-in', + ENERGY: 'charging-started', + TOURISM: 'ticket-purchased', +} +export const ORDER_DETAILS = { + domain: [ + {retail: { + orders: [ + { + orderId: '6', + orderFulfillmentStatus: '', + }, + { + orderId: '5', + orderFulfillmentStatus: '', + }, + { + orderId: '4', + orderFulfillmentStatus: '', + }, + { + orderId: '3', + orderFulfillmentStatus: '', + }, + { + orderId: '2', + orderFulfillmentStatus: '', + }, + ], + }}, + {hotel: { + orders: [ + { + orderId: '84', + orderFulfillmentStatus: '', + }, + { + orderId: '85', + orderFulfillmentStatus: '', + }, + { + orderId: '86', + orderFulfillmentStatus: '', + }, + { + orderId: '87', + orderFulfillmentStatus: '', + }, + { + orderId: '88', + orderFulfillmentStatus: '', + }, + ], + }}, + {tourism: { + orders: [ + { + orderId: '19', + orderFulfillmentStatus: '', + }, + { + orderId: '18', + orderFulfillmentStatus: '', + }, + { + orderId: '17', + orderFulfillmentStatus: '', + }, + { + orderId: '16', + orderFulfillmentStatus: '', + }, + { + orderId: '15', + orderFulfillmentStatus: '', + }, + ], + }}, + {energy: { + orders: [ + { + orderId: '27', + orderFulfillmentStatus: '', + }, + { + orderId: '28', + orderFulfillmentStatus: '', + }, + { + orderId: '29', + orderFulfillmentStatus: '', + }, + { + orderId: '30', + orderFulfillmentStatus: '', + }, + { + orderId: '31', + orderFulfillmentStatus: '', + }, + ], + }} + ] +}