From 5ea032d89522555f301c7c459973019dad2f615a Mon Sep 17 00:00:00 2001
From: Adhidarma Hadiwinoto <adhisimon@gmail.com>
Date: Wed, 19 Oct 2022 18:34:03 +0700
Subject: [PATCH] Product price

---
 lib/partner-listener/index.js                 |  2 +
 lib/partner-listener/routers/product-price.js | 99 +++++++++++++++++++++++++++
 lib/partner-listener/routers/product-tree.js  | 12 ++--
 package-lock.json                             | 81 ++++++++++++++++++----
 package.json                                  |  3 +-
 5 files changed, 177 insertions(+), 20 deletions(-)
 create mode 100644 lib/partner-listener/routers/product-price.js

diff --git a/lib/partner-listener/index.js b/lib/partner-listener/index.js
index 573d83a..e5c2ecc 100644
--- a/lib/partner-listener/index.js
+++ b/lib/partner-listener/index.js
@@ -14,6 +14,7 @@ const routerPay = require('./routers/pay');
 const routerTopup = require('./routers/topup');
 const routerTrxStatus = require('./routers/trx-status');
 const routerProductTree = require('./routers/product-tree');
+const routerProductPrice = require('./routers/product-price');
 
 const app = express();
 
@@ -50,6 +51,7 @@ app.use('/inquiry', routerInquiry);
 app.use('/pay', routerPay);
 app.use('/topup', routerTopup);
 app.use('/trx-status', routerTrxStatus);
+app.use('/product-price', routerProductPrice);
 app.use('/product-tree', routerProductTree);
 app.use('/', routerTopup);
 
diff --git a/lib/partner-listener/routers/product-price.js b/lib/partner-listener/routers/product-price.js
new file mode 100644
index 0000000..8168ac2
--- /dev/null
+++ b/lib/partner-listener/routers/product-price.js
@@ -0,0 +1,99 @@
+const MODULE_NAME = 'PARTNER-LISTENER.ROUTERS.PRODUCT-PRICE';
+
+const axios = require('axios').default;
+const express = require('express');
+const urlJoin = require('join-path');
+
+const coreUrl = require('komodo-sdk/core-url');
+const logger = require('tektrans-logger');
+const { orderBy } = require('natural-orderby');
+
+const ipv6ToIpv4 = require('../../ipv6-to-ipv4');
+const getFromBodyQsParams = require('../../get-from-body-qs-params');
+
+const CORE_ENDPOINT = urlJoin(coreUrl, '/product-tree');
+
+const router = express.Router();
+module.exports = router;
+
+const traverse = (data, productType) => {
+    const products = [];
+
+    if (Array.isArray(data)) {
+        data.forEach((brandCategory) => {
+            if (Array.isArray(brandCategory.brands)) {
+                brandCategory.brands.forEach((brand) => {
+                    if (Array.isArray(brand.product_categories)) {
+                        brand.product_categories.forEach((productCategory) => {
+                            if (Array.isArray(productCategory.products)) {
+                                productCategory.products.forEach((product) => {
+                                    products.push({
+                                        product: product.name,
+                                        description: product.description,
+                                        type: productType,
+                                        brandName: brand.name,
+                                        productCategory: productCategory.name,
+                                        price: product.price,
+                                    });
+                                });
+                            }
+                        });
+                    }
+                });
+            }
+        });
+    }
+
+    return products;
+};
+
+const mainHandler = async (req, res) => {
+    const { xid } = res.locals;
+
+    const terminalNameWithoutIp = (getFromBodyQsParams(req, 'terminal_name') || '').toString().trim();
+    const terminalName = `${terminalNameWithoutIp}@${ipv6ToIpv4(req.ip)}`;
+    const password = getFromBodyQsParams(req, 'password');
+
+    try {
+        const result = await axios.get(CORE_ENDPOINT, {
+            params: {
+                terminal_name: terminalName,
+                password,
+            },
+        });
+
+        if (!result || !result.data) {
+            const e = new Error(`${MODULE_NAME} 643A50C5: Invalid result from CORE`);
+            throw e;
+        }
+
+        const prepaidProducts = traverse(result.data.prepaid, 'PREPAID');
+        const postpaidProducts = traverse(result.data.postpaid, 'POSTPAID');
+
+        res.json({
+            httpgetx_xid: xid,
+            xid: result.data.xid,
+            ts: new Date(),
+            terminal_name: result.data.terminal_name,
+            products: orderBy(
+                prepaidProducts.concat(postpaidProducts),
+                (p) => p.product,
+                'asc',
+            ),
+        });
+    } catch (e) {
+        logger.warn(`${MODULE_NAME} A5414E86: Exception`, {
+            xid,
+            eCode: e.code,
+            eMessage: e.message || e,
+        });
+
+        res.json({
+            // httpgetx_xid: xid,
+            ts: new Date(),
+            error: e.message || e,
+        });
+    }
+};
+
+router.get('/', mainHandler);
diff --git a/lib/partner-listener/routers/product-tree.js b/lib/partner-listener/routers/product-tree.js
index 650e048..f1e7b81 100644
--- a/lib/partner-listener/routers/product-tree.js
+++ b/lib/partner-listener/routers/product-tree.js
@@ -2,11 +2,12 @@ const MODULE_NAME = 'PARTNER-LISTENER.ROUTERS.PRODUCT-TREE';
 
 const axios = require('axios').default;
 const express = require('express');
-const urlJoin = require('url-join');
+const urlJoin = require('join-path');
 
 const coreUrl = require('komodo-sdk/core-url');
 const logger = require('tektrans-logger');
 
+const ipv6ToIpv4 = require('../../ipv6-to-ipv4');
 const getFromBodyQsParams = require('../../get-from-body-qs-params');
 
 const CORE_ENDPOINT = urlJoin(coreUrl, '/product-tree');
@@ -17,7 +18,8 @@ module.exports = router;
 const mainHandler = async (req, res) => {
     const { xid } = res.locals;
 
-    const terminalName = getFromBodyQsParams(req, 'terminal_name');
+    const terminalNameWithoutIp = (getFromBodyQsParams(req, 'terminal_name') || '').toString().trim();
+    const terminalName = `${terminalNameWithoutIp}@${ipv6ToIpv4(req.ip)}`;
     const password = getFromBodyQsParams(req, 'password');
 
     try {
@@ -28,13 +30,13 @@ const mainHandler = async (req, res) => {
             },
         });
 
-        if (!result) {
+        if (!result || !result.data) {
             const e = new Error(`${MODULE_NAME} B7555411: Invalid result from CORE`);
             throw e;
         }
 
         result.httpgetx_xid = xid;
-        res.json(result);
+        res.json(result.data);
     } catch (e) {
         logger.warn(`${MODULE_NAME} 5AA99A06: Exception`, {
             xid,
@@ -43,7 +45,7 @@ const mainHandler = async (req, res) => {
         });
 
         res.json({
-            xid,
+            httpgetx_xid: xid,
             ts: new Date(),
             error: e.message || e,
         });
diff --git a/package-lock.json b/package-lock.json
index 1402424..236a393 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -11,13 +11,14 @@
       "dependencies": {
         "axios": "^0.19.2",
         "express": "^4.17.1",
+        "join-path": "^1.1.1",
         "komodo-sdk": "^1.45.6",
         "mkdirp": "^1.0.4",
         "moment": "^2.24.0",
+        "natural-orderby": "^2.0.3",
         "request": "^2.88.0",
         "tektrans-logger": "^1.2.3",
         "uniqid": "^5.3.0",
-        "url-join": "^5.0.0",
         "uuid": "^3.3.3"
       },
       "devDependencies": {
@@ -244,6 +245,11 @@
         "node": ">=0.10.0"
       }
     },
+    "node_modules/as-array": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/as-array/-/as-array-2.0.0.tgz",
+      "integrity": "sha512-1Sd1LrodN0XYxYeZcN1J4xYZvmvTwD5tDWaPUGPIzH1mFsmzsPnVtd2exWhecMjtZk/wYWjNZJiD3b1SLCeJqg=="
+    },
     "node_modules/asap": {
       "version": "2.0.6",
       "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
@@ -1996,6 +2002,21 @@
       "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
       "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
     },
+    "node_modules/join-path": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/join-path/-/join-path-1.1.1.tgz",
+      "integrity": "sha512-jnt9OC34sLXMLJ6YfPQ2ZEKrR9mB5ZbSnQb4LPaOx1c5rTzxpR33L18jjp0r75mGGTJmsil3qwN1B5IBeTnSSA==",
+      "dependencies": {
+        "as-array": "^2.0.0",
+        "url-join": "0.0.1",
+        "valid-url": "^1"
+      }
+    },
+    "node_modules/join-path/node_modules/url-join": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmjs.org/url-join/-/url-join-0.0.1.tgz",
+      "integrity": "sha512-H6dnQ/yPAAVzMQRvEvyz01hhfQL5qRWSEt7BX8t9DqnPw9BjMb64fjIRq76Uvf1hkHp+mTZvEVJ5guXOT0Xqaw=="
+    },
     "node_modules/js-tokens": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -2710,6 +2731,14 @@
       "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
       "dev": true
     },
+    "node_modules/natural-orderby": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/natural-orderby/-/natural-orderby-2.0.3.tgz",
+      "integrity": "sha512-p7KTHxU0CUrcOXe62Zfrb5Z13nLvPhSWR/so3kFulUQU0sgUll2Z0LwpsLN351eOOD+hRGu/F1g+6xDfPeD++Q==",
+      "engines": {
+        "node": "*"
+      }
+    },
     "node_modules/negotiator": {
       "version": "0.6.2",
       "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
@@ -4199,14 +4228,6 @@
         "punycode": "^2.1.0"
       }
     },
-    "node_modules/url-join": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/url-join/-/url-join-5.0.0.tgz",
-      "integrity": "sha512-n2huDr9h9yzd6exQVnH/jU5mr+Pfx08LRXXZhkLLetAMESRj+anQsTAh940iMrIetKAmry9coFuZQ2jY8/p3WA==",
-      "engines": {
-        "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
-      }
-    },
     "node_modules/util-deprecate": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
@@ -4235,6 +4256,11 @@
       "integrity": "sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==",
       "dev": true
     },
+    "node_modules/valid-url": {
+      "version": "1.0.9",
+      "resolved": "https://registry.npmjs.org/valid-url/-/valid-url-1.0.9.tgz",
+      "integrity": "sha512-QQDsV8OnSf5Uc30CKSwG9lnhMPe6exHtTXLRYX8uMwKENy640pU+2BgBL0LRbDh/eYRahNCS7aewCx0wf3NYVA=="
+    },
     "node_modules/validate-npm-package-license": {
       "version": "3.0.4",
       "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
@@ -4789,6 +4815,11 @@
       "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
       "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg="
     },
+    "as-array": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/as-array/-/as-array-2.0.0.tgz",
+      "integrity": "sha512-1Sd1LrodN0XYxYeZcN1J4xYZvmvTwD5tDWaPUGPIzH1mFsmzsPnVtd2exWhecMjtZk/wYWjNZJiD3b1SLCeJqg=="
+    },
     "asap": {
       "version": "2.0.6",
       "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
@@ -6208,6 +6239,23 @@
       "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
       "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
     },
+    "join-path": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/join-path/-/join-path-1.1.1.tgz",
+      "integrity": "sha512-jnt9OC34sLXMLJ6YfPQ2ZEKrR9mB5ZbSnQb4LPaOx1c5rTzxpR33L18jjp0r75mGGTJmsil3qwN1B5IBeTnSSA==",
+      "requires": {
+        "as-array": "^2.0.0",
+        "url-join": "0.0.1",
+        "valid-url": "^1"
+      },
+      "dependencies": {
+        "url-join": {
+          "version": "0.0.1",
+          "resolved": "https://registry.npmjs.org/url-join/-/url-join-0.0.1.tgz",
+          "integrity": "sha512-H6dnQ/yPAAVzMQRvEvyz01hhfQL5qRWSEt7BX8t9DqnPw9BjMb64fjIRq76Uvf1hkHp+mTZvEVJ5guXOT0Xqaw=="
+        }
+      }
+    },
     "js-tokens": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -6778,6 +6826,11 @@
       "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
       "dev": true
     },
+    "natural-orderby": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/natural-orderby/-/natural-orderby-2.0.3.tgz",
+      "integrity": "sha512-p7KTHxU0CUrcOXe62Zfrb5Z13nLvPhSWR/so3kFulUQU0sgUll2Z0LwpsLN351eOOD+hRGu/F1g+6xDfPeD++Q=="
+    },
     "negotiator": {
       "version": "0.6.2",
       "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
@@ -7932,11 +7985,6 @@
         "punycode": "^2.1.0"
       }
     },
-    "url-join": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/url-join/-/url-join-5.0.0.tgz",
-      "integrity": "sha512-n2huDr9h9yzd6exQVnH/jU5mr+Pfx08LRXXZhkLLetAMESRj+anQsTAh940iMrIetKAmry9coFuZQ2jY8/p3WA=="
-    },
     "util-deprecate": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
@@ -7958,6 +8006,11 @@
       "integrity": "sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==",
       "dev": true
     },
+    "valid-url": {
+      "version": "1.0.9",
+      "resolved": "https://registry.npmjs.org/valid-url/-/valid-url-1.0.9.tgz",
+      "integrity": "sha512-QQDsV8OnSf5Uc30CKSwG9lnhMPe6exHtTXLRYX8uMwKENy640pU+2BgBL0LRbDh/eYRahNCS7aewCx0wf3NYVA=="
+    },
     "validate-npm-package-license": {
       "version": "3.0.4",
       "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
diff --git a/package.json b/package.json
index 35aeb37..392374b 100644
--- a/package.json
+++ b/package.json
@@ -31,13 +31,14 @@
   "dependencies": {
     "axios": "^0.19.2",
     "express": "^4.17.1",
+    "join-path": "^1.1.1",
     "komodo-sdk": "^1.45.6",
     "mkdirp": "^1.0.4",
     "moment": "^2.24.0",
+    "natural-orderby": "^2.0.3",
     "request": "^2.88.0",
     "tektrans-logger": "^1.2.3",
     "uniqid": "^5.3.0",
-    "url-join": "^5.0.0",
     "uuid": "^3.3.3"
   }
 }
-- 
1.9.0