first commit
This commit is contained in:
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
node_modules/
|
||||||
|
package-lock.json
|
||||||
|
.env
|
||||||
|
storage/html/*
|
||||||
|
!storage/html/.gitignore
|
||||||
71
config/index.js
Normal file
71
config/index.js
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
const commandLineArgs = require('command-line-args')
|
||||||
|
, xmlParserConfig = require('./xmlParserConfig')
|
||||||
|
, godoParams = require('./params.json')
|
||||||
|
, logger = require("logops");
|
||||||
|
|
||||||
|
class Config {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.options = {}
|
||||||
|
this.requires = ['env', 'gateway', 'quix24', 'mongo']
|
||||||
|
this.init()
|
||||||
|
this.validate()
|
||||||
|
this.finalize()
|
||||||
|
}
|
||||||
|
|
||||||
|
init() {
|
||||||
|
try {
|
||||||
|
this.options = commandLineArgs([
|
||||||
|
{ name: 'env', alias: 'e', type: String, defaultValue: ['production'] },
|
||||||
|
{ name: 'host', type: String },
|
||||||
|
{ name: 'port', type: Number },
|
||||||
|
{ name: 'database', alias: 'd', type: String },
|
||||||
|
{ name: 'username', alias: 'u', type: String },
|
||||||
|
{ name: 'password', alias: 'p', type: String },
|
||||||
|
{ name: 'mongo', alias: 'm', type: String },
|
||||||
|
{ name: 'redis', alias: 'r', type: String },
|
||||||
|
{ name: 'level', alias: 'l', type: String },
|
||||||
|
{ name: 'gateway', alias: 'g', type: String },
|
||||||
|
{ name: 'quix24', alias: 'q', type: String }
|
||||||
|
]);
|
||||||
|
} catch (e) {
|
||||||
|
logger.debug('Command line arguments interpret failed :', e.message)
|
||||||
|
logger.debug('expected arguments : ', JSON.stringify(this.requires))
|
||||||
|
process.exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
finalize() {
|
||||||
|
if (this.options.env == 'development') {
|
||||||
|
this.options.level = this.options.level ? this.options.level : "DEBUG"
|
||||||
|
logger.formatters.dev.omit = ['pid', 'port', 'hostname', 'app'];
|
||||||
|
// logger.format = logger.formatters.dev;
|
||||||
|
} else {
|
||||||
|
this.options.level = this.options.level ? this.options.level : "WARN"
|
||||||
|
}
|
||||||
|
this.options.xmlParser = xmlParserConfig
|
||||||
|
this.options.godoParams = godoParams
|
||||||
|
logger.formatters.json.omit = ['pid', 'port', 'hostname', 'app'];
|
||||||
|
logger.setLevel(this.options.level)
|
||||||
|
logger.debug(this.options, 'Environment setting options')
|
||||||
|
}
|
||||||
|
|
||||||
|
validate() {
|
||||||
|
for (let key in this.options) {
|
||||||
|
if (this.options[key]) {
|
||||||
|
delete this.requires[this.requires.indexOf(key)]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.requires = this.requires.filter(function (el) {
|
||||||
|
return el != null;
|
||||||
|
})
|
||||||
|
if (this.requires.length) {
|
||||||
|
logger.debug('Process terminated invalid required arguments: ', JSON.stringify(this.requires))
|
||||||
|
process.exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
let config = new Config;
|
||||||
|
module.exports = config.options
|
||||||
4
config/params.json
Normal file
4
config/params.json
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"partner_key": "JUFDJUIzJTAyJTVEJTk5JTE5JUYwRw==",
|
||||||
|
"key": "JTVFJTE0JUZCJUVGJUQ2SSUxNiU4RCVCMyVGOSU3RSVGRCVGNSVGNyUxNSU3RCVBM0YlRDAlMkNwJUNDJUQ2JUNDVSU5MCUzRWklN0YlOEIlQUQlRTMlQURqYSVCQiUwOSUwMCVDMCUwOCVFRiVGQyVDQk0="
|
||||||
|
}
|
||||||
20
config/xmlParserConfig.js
Normal file
20
config/xmlParserConfig.js
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
const he = require('he')
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
"attributeNamePrefix": "@_",
|
||||||
|
"attrNodeName": "attr", //default is 'false'
|
||||||
|
"textNodeName": "#text",
|
||||||
|
"ignoreAttributes": true,
|
||||||
|
"ignoreNameSpace": false,
|
||||||
|
"allowBooleanAttributes": false,
|
||||||
|
"parseNodeValue": true,
|
||||||
|
"parseAttributeValue": false,
|
||||||
|
"trimValues": true,
|
||||||
|
// "cdataTagName": "__cdata", //default is 'false'
|
||||||
|
"cdataPositionChar": "\\c",
|
||||||
|
"parseTrueNumberOnly": false,
|
||||||
|
"arrayMode": false, //"strict"
|
||||||
|
"attrValueProcessor": (val, attrName) => he.decode(val, { isAttributeValue: true }),//default is a=>a
|
||||||
|
"tagValueProcessor": (val, tagName) => he.decode(val), //default is a=>a
|
||||||
|
"stopNodes": ["parse-me-as-string"]
|
||||||
|
}
|
||||||
60
index.js
Normal file
60
index.js
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
const config = require('./config')
|
||||||
|
, express = require("express")
|
||||||
|
, expressLogging = require("express-logging")
|
||||||
|
, logger = require("logops")
|
||||||
|
, { StatusCodes, getReasonPhrase } = require('http-status-codes')
|
||||||
|
, hostname = require('os').hostname()
|
||||||
|
, port = 32105
|
||||||
|
, godoUpdater = require('./src/component/GodoUpdater')
|
||||||
|
, controllers = {};
|
||||||
|
|
||||||
|
|
||||||
|
process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Express web server starting
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
logger.getContext = function getContext() {
|
||||||
|
return {
|
||||||
|
// hostname: hostname,
|
||||||
|
// pid: process.pid,
|
||||||
|
// port: port,
|
||||||
|
app: 'Godo'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
var app = express();
|
||||||
|
app.use(express.json());
|
||||||
|
app.use(expressLogging(logger));
|
||||||
|
app.use((req, res, next) => {
|
||||||
|
logger.debug(Object.assign(req.body, req.query, req.params), 'Request params')
|
||||||
|
next()
|
||||||
|
})
|
||||||
|
app.listen(port, () => {
|
||||||
|
logger.info('Service started')
|
||||||
|
if(config.env == 'production')
|
||||||
|
godoUpdater.start()
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request handlers
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
app.all('*', (req, res, next) => {
|
||||||
|
let urlSegments = req.url.split('/');
|
||||||
|
req.params.service = urlSegments[1]
|
||||||
|
req.params.what = urlSegments.length > 2 ? urlSegments[2] : ''
|
||||||
|
req.params.args = urlSegments.length > 3 ? urlSegments.slice(3) : []
|
||||||
|
|
||||||
|
if(!controllers.hasOwnProperty(req.params.service)) {
|
||||||
|
let controller = req.params.service.charAt(0).toUpperCase() + req.params.service.slice(1) + 'Controller';
|
||||||
|
controllers[req.params.service] = require('./src/controller/' + controller)
|
||||||
|
logger.info('%s has been loaded', controller)
|
||||||
|
}
|
||||||
|
controllers[req.params.service][req.params.service](req, result => {
|
||||||
|
let body = { code: StatusCodes.OK, message: getReasonPhrase(StatusCodes.OK), data: result }
|
||||||
|
if(result.code) body = result
|
||||||
|
res.json(body)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
31
package.json
Normal file
31
package.json
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
"name": "spd-app-godo",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://spiduler:GD4eYvJMHUkXmajs@github.com/spiduler/spd-app-godo.git"
|
||||||
|
},
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/spiduler/spd-app-godo/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/spiduler/spd-app-godo#readme",
|
||||||
|
"dependencies": {
|
||||||
|
"command-line-args": "^5.1.1",
|
||||||
|
"express": "^4.17.1",
|
||||||
|
"express-logging": "^1.1.1",
|
||||||
|
"fast-xml-parser": "^3.17.4",
|
||||||
|
"form-data": "^3.0.0",
|
||||||
|
"he": "^1.2.0",
|
||||||
|
"http-status-codes": "^2.1.4",
|
||||||
|
"logops": "^2.1.1",
|
||||||
|
"mongodb": "^3.6.2",
|
||||||
|
"node-fetch": "^2.6.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
53
src/component/GodoClient.js
Normal file
53
src/component/GodoClient.js
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
const config = require('../../config')
|
||||||
|
, fetch = require('node-fetch')
|
||||||
|
, parser = require('fast-xml-parser')
|
||||||
|
, logger = require('logops')
|
||||||
|
, FormData = require('form-data')
|
||||||
|
, { getReasonPhrase, StatusCodes } = require('http-status-codes')
|
||||||
|
|
||||||
|
|
||||||
|
class GodoClient {
|
||||||
|
constructor() {
|
||||||
|
this.host = 'https://openhub.godo.co.kr/godomall5/'
|
||||||
|
}
|
||||||
|
|
||||||
|
convertObj2FormData(params) {
|
||||||
|
let form = new FormData
|
||||||
|
Object.keys(params).forEach(key => {
|
||||||
|
form.append(key, params[key])
|
||||||
|
})
|
||||||
|
return form
|
||||||
|
}
|
||||||
|
|
||||||
|
formatResult(data) {
|
||||||
|
return data
|
||||||
|
for (let k in data) {
|
||||||
|
if (data[k].__cdata) data[k] = data[k]
|
||||||
|
}
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
request(url, params) {
|
||||||
|
params = Object.assign(config.godoParams, params)
|
||||||
|
logger.debug(params, 'params')
|
||||||
|
return fetch(this.host + url, {
|
||||||
|
method: 'POST',
|
||||||
|
body: this.convertObj2FormData(params)
|
||||||
|
}).then(res => res.text()).then(body => {
|
||||||
|
let data = null
|
||||||
|
if (parser.validate(body) === true) {
|
||||||
|
data = parser.parse(body, config.xmlParser);
|
||||||
|
} else {
|
||||||
|
logger.debug({ body: body, url: url }, 'Invalid godo respose body')
|
||||||
|
}
|
||||||
|
return this.formatResult(data)
|
||||||
|
}).catch(err => {
|
||||||
|
logger.error(err.message, 'Unexpected error occured while requesting')
|
||||||
|
return { code: StatusCodes.PRECONDITION_FAILED, message: getReasonPhrase(StatusCodes.PRECONDITION_FAILED) }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = new GodoClient
|
||||||
103
src/component/GodoUpdater.js
Normal file
103
src/component/GodoUpdater.js
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
const { StatusCodes, getReasonPhrase } = require('http-status-codes')
|
||||||
|
, restClient = require('./RestClient')
|
||||||
|
, godoClient = require('../component/GodoClient')
|
||||||
|
, fetch = require("node-fetch")
|
||||||
|
, productService = require('../service/ProductService')
|
||||||
|
, logger = require('logops')
|
||||||
|
|
||||||
|
|
||||||
|
class GodoUpdater {
|
||||||
|
constructor() {
|
||||||
|
this.endDate = null
|
||||||
|
this.config = {
|
||||||
|
catalogSearch: {
|
||||||
|
skip: 0,
|
||||||
|
limit: 10
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sleep(ms) {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
setTimeout(resolve, ms);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
start() {
|
||||||
|
this.startUpdate()
|
||||||
|
// setInterval(() => this.startUpdate(), 1000 * 3 * this.config.catalogSearch.limit)
|
||||||
|
}
|
||||||
|
|
||||||
|
startUpdate() {
|
||||||
|
productService.searchCatalogId(this.config.catalogSearch).then(async res => {
|
||||||
|
logger.debug({resultCode: res.code}, 'Search Catalogs and Images %s', res.message)
|
||||||
|
this.config.catalogSearch.skip = this.config.catalogSearch.skip + this.config.catalogSearch.limit
|
||||||
|
if (res.code == StatusCodes.OK) {
|
||||||
|
this.update(res.data.rows).then(godoUpdateResult => {
|
||||||
|
logger.debug(godoUpdateResult, 'Godo product update result')
|
||||||
|
if (godoUpdateResult.length) {
|
||||||
|
this.updateCatalog(godoUpdateResult).then(updateCatalgResult => {
|
||||||
|
logger.debug({
|
||||||
|
modifiedCount: updateCatalgResult.map(r => {
|
||||||
|
if (r.data.modifiedCount > 0) return true
|
||||||
|
}).filter(r => r).length
|
||||||
|
}, 'Update catalog adding godo goodsNo result count : %d', updateCatalgResult.length)
|
||||||
|
this.startUpdate()
|
||||||
|
})
|
||||||
|
}else {
|
||||||
|
this.startUpdate()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
} else if (res.code == StatusCodes.NOT_FOUND) {
|
||||||
|
this.resetCatalogSearchQuery()
|
||||||
|
await this.sleep(1000 * 2)
|
||||||
|
this.startUpdate()
|
||||||
|
} else if (res.code == StatusCodes.NO_CONTENT) {
|
||||||
|
await this.sleep(1000 * 2)
|
||||||
|
this.startUpdate()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async update(catalogsId) {
|
||||||
|
let results = []
|
||||||
|
let promises = []
|
||||||
|
for (let ck in catalogsId) {
|
||||||
|
await this.sleep(1000 * 1)
|
||||||
|
let c = catalogsId[ck]
|
||||||
|
promises.push(productService.post({ id: c.id }, result => {
|
||||||
|
if (result.header.code === 0) {
|
||||||
|
results.push(Object.assign(c, { godoId: result.return.goods_data.data.goodsno }))
|
||||||
|
} else {
|
||||||
|
logger.debug({ code: result.header.code, reason: result.header.msg }, 'Godo update failed')
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
await Promise.all(promises)
|
||||||
|
return results
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateCatalog(godoUpdateResult) {
|
||||||
|
let updateCatalogResult = []
|
||||||
|
let promises = []
|
||||||
|
for (let k in godoUpdateResult) {
|
||||||
|
await this.sleep(1000 * 1)
|
||||||
|
let result = godoUpdateResult[k]
|
||||||
|
let params = { clause: { site: result.site, ean: result.ean }, data: { godoId: result.godoId, legacyId: result.id } }
|
||||||
|
promises.push(productService.updateCatalog(params).then(res => {
|
||||||
|
if (res.code == StatusCodes.OK) {
|
||||||
|
updateCatalogResult.push(res)
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
await Promise.all(promises)
|
||||||
|
return updateCatalogResult
|
||||||
|
}
|
||||||
|
|
||||||
|
resetCatalogSearchQuery() {
|
||||||
|
this.config.catalogSearch.skip = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = new GodoUpdater
|
||||||
53
src/component/RestClient.js
Normal file
53
src/component/RestClient.js
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
const fetch = require("node-fetch")
|
||||||
|
, logger = require("logops")
|
||||||
|
, TokenExpiredException = require('../exception/TokenExpiredException')
|
||||||
|
, config = require('../../config');
|
||||||
|
|
||||||
|
|
||||||
|
class RestClient {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.token = null
|
||||||
|
this.gateway = 'http://' + config.gateway + '/api/v1/'
|
||||||
|
this.clientId = '7tmK4rF8As8CtRw5'
|
||||||
|
this.clientSecret = 'cgzLcVFku5zEvXkCKNZsAbxXQENFqPDx2kfjnMGd3m9BczehmFt2pw9r9MdASSFt'
|
||||||
|
}
|
||||||
|
|
||||||
|
auth() {
|
||||||
|
let url = this.gateway + 'oauth/token?client_id=' + this.clientId + '&grant_type=client_credentials&client_secret=' + this.clientSecret
|
||||||
|
return fetch(url, { method: 'GET', headers: { 'content-type': 'application/json' } }).then(res => res.json()).then(res => {
|
||||||
|
logger.debug(res, 'Token from %s', this.gateway)
|
||||||
|
this.token = res.access_token
|
||||||
|
return res.access_token
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
headers(additionalheaders) {
|
||||||
|
let headers = {
|
||||||
|
"Authorization": "Bearer " + this.token,
|
||||||
|
"Content-Type": "application/json"
|
||||||
|
}
|
||||||
|
return additionalheaders ? Object.assign(headers, additionalheaders) : headers
|
||||||
|
}
|
||||||
|
|
||||||
|
response(res) {
|
||||||
|
if (res.code == 406) {
|
||||||
|
throw new TokenExpiredException("Token expired " + this.gateway)
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
async request(fetchable) {
|
||||||
|
if (!this.token) await this.auth()
|
||||||
|
return fetchable().catch(error => {
|
||||||
|
logger.error({ message: error.message }, 'Fetchable failed with error')
|
||||||
|
if (error.status == 406) {
|
||||||
|
logger.info('Requesting token %s', this.gateway)
|
||||||
|
return this.auth().then(() => fetchable())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = RestClient;
|
||||||
32
src/controller/ProductController.js
Normal file
32
src/controller/ProductController.js
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
const logger = require("logops")
|
||||||
|
, productService = require('../service/ProductService');
|
||||||
|
|
||||||
|
class ProductController {
|
||||||
|
getMethodName(req) {
|
||||||
|
return req.method.toLowerCase()
|
||||||
|
+ req.params.what.split('_').map(w => w.charAt(0).toUpperCase() + w.slice(1)).join('')
|
||||||
|
}
|
||||||
|
|
||||||
|
product(req, callback) {
|
||||||
|
let fn = this.getMethodName(req);
|
||||||
|
let params = req.body
|
||||||
|
logger.info('Invoking method ProductService.%s', fn)
|
||||||
|
if (typeof this[fn] === 'function') {
|
||||||
|
this[fn](params, callback)
|
||||||
|
} else callback({ code: 500, message: 'Method not found' })
|
||||||
|
}
|
||||||
|
|
||||||
|
get(params, callback) {
|
||||||
|
productService.get(params, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
post(params, callback) {
|
||||||
|
productService.post(params, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
postSummary(params, callback) {
|
||||||
|
productService.searchCatalogId(params).then(result => callback(result));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = new ProductController;
|
||||||
16
src/exception/TokenExpiredException.js
Normal file
16
src/exception/TokenExpiredException.js
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
class TokenExpiredException extends Error {
|
||||||
|
constructor (message) {
|
||||||
|
super(message)
|
||||||
|
|
||||||
|
// assign the error class name in your custom error (as a shortcut)
|
||||||
|
this.name = this.constructor.name
|
||||||
|
|
||||||
|
// capturing the stack trace keeps the reference to your error class
|
||||||
|
Error.captureStackTrace(this, this.constructor);
|
||||||
|
|
||||||
|
// you may also assign additional properties to your error
|
||||||
|
this.status = 406
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = TokenExpiredException
|
||||||
31
src/service/CatalogService.js
Normal file
31
src/service/CatalogService.js
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
const fetch = require("node-fetch")
|
||||||
|
, logger = require("logops")
|
||||||
|
, RestClient = require('../component/RestClient')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class ProductService {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.restClient = new RestClient
|
||||||
|
}
|
||||||
|
|
||||||
|
post(params, additionalheaders) {
|
||||||
|
return this.restClient.request(() => fetch(this.restClient.gateway + 'catalog', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: this.restClient.headers(additionalheaders),
|
||||||
|
body: JSON.stringify(params)
|
||||||
|
}).then(res => res.json()).then(res => this.restClient.response(res))).then(res => res.data)
|
||||||
|
}
|
||||||
|
|
||||||
|
get(params, additionalheaders) {
|
||||||
|
return this.restClient.request(() => fetch(this.restClient.gateway + 'catalog/search', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: this.restClient.headers(additionalheaders),
|
||||||
|
body: JSON.stringify(params)
|
||||||
|
}).then(res => res.json()).then(res => this.restClient.response(res))).then(res => res.data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = new ProductService;
|
||||||
118
src/service/ProductService.js
Normal file
118
src/service/ProductService.js
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
const fetch = require("node-fetch")
|
||||||
|
, logger = require("logops")
|
||||||
|
, godoClient = require('../component/GodoClient')
|
||||||
|
, RestClient = require("../component/RestClient")
|
||||||
|
, { StatusCodes, getReasonPhrase } = require('http-status-codes')
|
||||||
|
|
||||||
|
|
||||||
|
class ProductService extends RestClient {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super()
|
||||||
|
}
|
||||||
|
|
||||||
|
get(params, callback) {
|
||||||
|
return godoClient.request('goods/Goods_Search.php', {}).then(data => {
|
||||||
|
callback(data)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
post(params, callback) {
|
||||||
|
return godoClient.request('goods/Goods_Insert.php', { data_url: 'http://www.ibspot.eu/app/open/godo/product/' + params.id + '.xml' }).then(data => {
|
||||||
|
callback(data.data)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
updateCatalog(data) {
|
||||||
|
return this.request(() => fetch(this.gateway + 'ext/catalog', {
|
||||||
|
method: 'PUT',
|
||||||
|
headers: this.headers(),
|
||||||
|
body: JSON.stringify(data)
|
||||||
|
}).then(res => res.json()).then(res => this.response(res))).catch(err => {
|
||||||
|
logger.error({ reason: err.message }, 'Catalog search failed')
|
||||||
|
return { code: 500, message: err.message }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
searchCatalog(data) {
|
||||||
|
return this.request(() => fetch(this.gateway + 'ext/catalog/search', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: this.headers(),
|
||||||
|
body: JSON.stringify(data)
|
||||||
|
}).then(res => res.json()).then(res => this.response(res))).catch(err => {
|
||||||
|
logger.error({ reason: err.message }, 'Catalog search failed')
|
||||||
|
return { code: 500, message: err.message }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
findCatalog(data) {
|
||||||
|
return this.request(() => fetch(this.gateway + 'ext/catalog/find', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: this.headers(),
|
||||||
|
body: JSON.stringify(data)
|
||||||
|
}).then(res => res.json()).then(res => this.response(res))).catch(err => {
|
||||||
|
logger.error({ reason: err.message }, 'Catalog find failed')
|
||||||
|
return { code: 500, message: err.message }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
searchImage(data) {
|
||||||
|
return this.request(() => fetch(this.gateway + 'ext/catalog/image_search', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: this.headers(),
|
||||||
|
body: JSON.stringify(data)
|
||||||
|
}).then(res => res.json()).then(res => this.response(res))).catch(err => {
|
||||||
|
logger.error({ reason: err.message }, 'Catalog image search failed')
|
||||||
|
return { code: 500, message: err.message }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
searchCatalogId(params) {
|
||||||
|
return this.searchImage(params).then(imageRes => {
|
||||||
|
if (imageRes.code == StatusCodes.OK && imageRes.data.length) {
|
||||||
|
let images = imageRes.data
|
||||||
|
// let barcodes = []
|
||||||
|
// images.map(image => {
|
||||||
|
// barcodes = barcodes.concat(image.ean)
|
||||||
|
// })
|
||||||
|
// multi ean product has array of ean in image collection so, should treat as one product
|
||||||
|
let barcodes = images.map(image => {
|
||||||
|
return image.ean[0]
|
||||||
|
})
|
||||||
|
return this.searchCatalog({ ean: { $in: barcodes }, godoId: { $exists: false } }).then(catalogRes => {
|
||||||
|
if (catalogRes.code == StatusCodes.OK && catalogRes.data.length) {
|
||||||
|
let summary = catalogRes.data.map(c => {
|
||||||
|
for (let ik in images) {
|
||||||
|
if (images[ik].ean.includes(c.ean) && c.site == images[ik].site) {
|
||||||
|
c.image = images[ik]
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return this.findCatalog({ barcode: barcodes }).then(res => {
|
||||||
|
if (res.code == StatusCodes.OK && res.data.length) {
|
||||||
|
let catalogsId = res.data.map(c => {
|
||||||
|
for (let s in summary) {
|
||||||
|
if (c.Barcode == summary[s].ean && c.SpiderSite == summary[s].site) {
|
||||||
|
return { id: c.Id, site: c.SpiderSite, ean: c.Barcode }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).filter(id => id)
|
||||||
|
return { code: StatusCodes.OK, message: getReasonPhrase(StatusCodes.OK), data: { rows: catalogsId, total: catalogsId.length } }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
return { code: StatusCodes.NO_CONTENT, message: getReasonPhrase(StatusCodes.NO_CONTENT) + ' Catalog' }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
return { code: StatusCodes.NOT_FOUND, message: getReasonPhrase(StatusCodes.NOT_FOUND) + ' Image' }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = new ProductService;
|
||||||
27
test.js
Normal file
27
test.js
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
// new Promise(resolve => {
|
||||||
|
// resolve('abc')
|
||||||
|
// }).then(abc => {
|
||||||
|
// throw new Error("aaaa")
|
||||||
|
// }).then(a => {
|
||||||
|
// console.log('adsf')
|
||||||
|
// }).catch(err => {
|
||||||
|
// console.log(err.message)
|
||||||
|
// }).then(d => console.log(d))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
goodsNm: a
|
||||||
|
goodsNo: a
|
||||||
|
goodsCd: a
|
||||||
|
makerNm: a
|
||||||
|
originNm: a
|
||||||
|
goodsSearchWord: a
|
||||||
|
goodsModelNo: a
|
||||||
|
companyNm: a
|
||||||
|
searchDateType: a
|
||||||
|
startDate: a
|
||||||
|
endDate: a
|
||||||
|
page: a
|
||||||
|
size: a
|
||||||
|
scmNo: a
|
||||||
|
cateCd: a
|
||||||
Reference in New Issue
Block a user