first commit

This commit is contained in:
pakerpale
2020-08-28 02:08:23 +09:00
commit b8899d1d4e
24 changed files with 3865 additions and 0 deletions

51
src/Amazon.js Executable file
View File

@@ -0,0 +1,51 @@
const Product = require('./Product')
, parser = require('./Parser')
, client = require('./Client');
const amazon = {
us: {
data: {
url: 'https://www.amazon.com',
categories: {},
subcategories: {}
},
utils: {
fakeTitle: (length, calls, leadingTxt) => {
let result = '';
let characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
let charactersLength = characters.length;
for (var i = 0; i < length; i++) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
}
let lengthRand = length //Math.ceil(Math.random(3, length))
return --calls ? amazon.us.utils.fakeTitle(lengthRand, calls, leadingTxt + result + '-') : leadingTxt + result;
}
},
task: {
categories: () => {
return client.request({ amazon: amazon, call: 'categories' }).then(parser.categories);
},
subCategories: (category) => {
return client.request({ amazon: amazon, category: category, call: 'subCategories' }).then(parser.subCategories);
},
productLink: (link) => {
return client.request({ amazon: amazon, link: link, call: 'productLinks' }).then(parser.productLinks);
},
productDetail: (asin) => {
let product = new Product()
return product.fetch(amazon, asin)
},
offerListing: (asin) => {
return client.request({ amazon: amazon, asin:asin, call: 'offerListing' }).then(parser.offerListing);
}
}
}
}
module.exports = amazon;

53
src/Client.js Executable file
View File

@@ -0,0 +1,53 @@
const fetch = require("node-fetch");
const Client = {
headers: {
'authority' : 'www.amazon.com',
'method' : 'GET',
'path' : '',
'scheme' : 'https',
'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3',
'accept-encoding' : 'gzip, deflate, br',
'accept-language' : 'ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7',
'cache-control' : 'max-age=0',
'sec-fetch-mode' : 'navigate',
'sec-fetch-site' : 'none',
'sec-fetch-user' : '?1',
'upgrade-insecure-requests' : '1',
'user-agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36',
cookie: 'lc-main=ko_KR;i18n-prefs=KRW'
},
request: async (args) => {
let url = Client[args.call](args)
Client.headers['path'] = url.replace(args.amazon.us.data.url, '')
return fetch(url, { headers: Client.headers }).then(res => res.textConverted());
},
offerListing: (args) => {
let url = args.amazon.us.data.url + '/dp/offer-listing/' + args.asin + '/ref=dp_olp_new_mbc?ie=UTF8&condition=new';
console.log('- request product offer listing page url : ' + url);
return url;
},
productDetail: (args) => {
let url = args.amazon.us.data.url + '/' + args.amazon.us.utils.fakeTitle(7, 4, '') + '/dp/' + args.asin;
console.log('- request product detail page url : ' + url);
return url;
},
categories: (args) => {
let url = args.amazon.us.data.url + '/gp/site-directory';
console.log('- request category page url : ' + url)
return url;
},
subCategories: (args) => {
let url = args.amazon.us.data.url + args.category.link;
console.log('- request sub category page url : ' + url)
return url;
},
productLinks: (args) => {
let url = args.amazon.us.data.url + args.link;
console.log('- request product links page url : ' + url)
return url;
}
}
module.exports = Client;

54
src/Parser.js Executable file
View File

@@ -0,0 +1,54 @@
const cheerio = require("cheerio");
const Parser = {
categories: body => {
let data = []
const $ = cheerio.load(body)
$(".a-container a").map((k, v) => {
data.push({
link: $(v).attr('href'),
title: $(v).text()
});
})
console.log('- fetching ' + data.length + ' category links completed')
return data
},
subCategories: body => {
let data = []
const $ = cheerio.load(body)
$(".left_nav.browseBox li a").map((k, v) => {
data.push({
link: $(v).attr('href'),
title: $(v).text()
});
})
return data;
},
productLinks: body => {
let data = []
const $ = cheerio.load(body)
$("#mainResults a.a-link-normal").map((k, v) => {
let title = $(v).find('h2').text().trim();
if (title) {
data.push({
link: $(v).attr('href'),
title: title
});
}
})
// console.log(data)
amazon.us.data.subcategories = data;
data.forEach((v, k) => {
console.log(v.link)
})
},
offerListing: body => {
const $ = cheerio.load(body)
let stock = $('#olpOfferList .a-row.olpOffer').length;
let price = $('#olpOfferList div.a-column.a-span2.olpPriceColumn').last().find('span').text().trim();
return {stock: stock, price: price}
}
}
module.exports = Parser

118
src/Product.js Executable file
View File

@@ -0,0 +1,118 @@
const cheerio = require("cheerio")
, client = require('./Client');
class Product {
constructor() {
this.data = {}
this.amazon = null
}
async fetch(amazon, asin) {
this.amazon = amazon;
let args = [{ amazon: this.amazon, asin: asin, call: 'productDetail', resolver: 'parseHtmlDetail' },
{ amazon: this.amazon, asin: asin, call: 'offerListing', resolver: 'parseHtmlOfferListing' }]
let fetchPromises = args.map(async args => {
return await client.request(args)
})
for (let k in fetchPromises) {
await fetchPromises[k].then(body => this[args[k].resolver](body))
}
this.data.asin = asin
return this.data
}
parseHtmlDetail(body) {
let $ = cheerio.load(body)
this.data.title = $('#productTitle').text().trim()
let merchant = $('#merchant-info a');
if (!merchant.length) {
merchant = $('#merchant-info');
}
this.data.seller = {
title: merchant.text().replace('에서 판매하고 배송합니다.', '').replace('주문 처리', '').trim(),
link: merchant.attr('href')
}
this.data.img = $('#landingImage').attr('src')
this.data.description = this.description(this.amazon, $)
this.data.category = this.category(this.amazon, $)
this.data.price = this.price(this.amazon, $)
this.data.colors = this.colors(this.amazon, $)
this.data.colorsASIN = this.colorsASIN(this.amazon, $)
}
description(amazon, $) {
return {
content: $('#aplus').html(),
spec: $('#descriptionAndDetails').html(),
videos: function () {
if ($('#vse-rel-videos-carousel ol li a').length) {
return {
link: amazon.us.data.url + $('#vse-rel-videos-carousel ol li a').eq(0).attr('href'),
title: $('#vse-rel-videos-carousel ol li a div.vse-video-content .vse-video-title-text').eq(0).text().trim()
}
} else return {}
}()
}
}
parseHtmlOfferListing(body) {
let $ = cheerio.load(body)
let stock = $('#olpOfferList .a-row.olpOffer').length;
let price = $('#olpOfferList div.a-column.a-span2.olpPriceColumn').last().find('span').text().trim();
// let seller = $('#olpOfferList .olpSellerName').last().find('span a').text().trim();
// let sellerLink = $('#olpOfferList .olpSellerName').last().find('span a').attr('href');
this.data.stock = stock;
this.data.price = price;
// this.data.seller = { title: seller, link: sellerLink }
}
category(amazon, $) {
let categoryPath = []
$('#wayfinding-breadcrumbs_feature_div li a').map((k, n) => {
categoryPath.push({ title: $(n).text().trim(), link: amazon.us.data.url + $(n).attr('href') })
})
return categoryPath
}
price(amazon, $) {
let price;
price = $('#olp-upd-new > span > a').eq(0).text().trim()
if (price) {
if (price.split('$').length == 2) {
return '$' + price.split('$')[1]
}
}
price = $('#priceblock_ourprice').text().trim()
if (price) return price
}
colors(amazon, $) {
let colors = []
$('li[id^=color_name_]').map((k, n) => {
colors.push({
img: $(n).find('img').attr('src'),
title: $(n).find('img').attr('alt'),
})
})
return colors
}
colorsASIN(amazon, $) {
let colorsASIN = []
$('li[id^=color_name_]').map((k, n) => {
let asin = $(n).attr('data-defaultasin');
if (!asin) {
asin = $(n).attr('data-dp-url').split('/')[2];
}
colorsASIN.push(asin)
})
return colorsASIN
}
}
module.exports = Product;

View File

@@ -0,0 +1,117 @@
const logger = require('logops')
, db = require("../model");
class PurchaseComponent {
getPurchaseData(data, now) {
return {
OrgCode: data.orgCode,
PurchaseNo: data.purchaseNo,
Status: data.status,
CreatedAt: now
}
}
getPurchaseItemData(itemData, purchase, now) {
return itemData.map(item => {
return {
PurchaseId: purchase.Id,
ItemLink: item.itemLink,
ItemName: item.itemName,
ItemBrand: item.itemBrand,
ItemUnitPrice: item.itemUnitPrice,
ItemTax: item.itemTax,
ItemCount: item.itemCount,
Status: item.status,
CreatedAt: now
}
})
}
getSearchPurchaseItemClause(params) {
let clause = { where: {}, raw: true }
if (params.purchaseId) {
clause.where.PurchaseId = Array.isArray(params.purchaseId) ? { [db.Sequelize.Op.in]: params.purchaseId } : params.purchaseId
}
if (params.id) {
clause.where.Id = Array.isArray(params.id) ? { [db.Sequelize.Op.in]: params.id } : params.id
}
if (params.sdate && params.edate) {
clause.where[params.daterangeby ? params.daterangeby : 'CreatedAt'] = { [db.Sequelize.Op.between]: [params.sdate, params.edate] }
}
if (params.limit) {
clause.limit = parseInt(params.limit)
}
if (params.offset) {
clause.offset = parseInt(params.offset)
}
if (params.column) {
clause.attributes = Array.isArray(params.column) ? params.column : [params.column]
}
if (params.sort) {
clause.order = [
[params.sort, params.order ? params.order.toUpperCase() : 'ASC']
]
}
return clause
}
findPurchaseById(purchaseId) {
let purchases = {}
return db.purchase.findAll({ where: { Id: { [db.Sequelize.Op.in]: purchaseId } } }).then(rows => {
rows.forEach(p => {
purchases[p.Id] = p
})
return purchases
})
}
findPurchaseItemOptionByItemId(purchaseItemId) {
let itemOptions = {}
let clause = { where: { ItemId: { [db.Sequelize.Op.in]: purchaseItemId } } }
return db.purchaseItemOption.findAll(clause).then(options => {
options.forEach(opt => {
if (itemOptions.hasOwnProperty(opt.ItemId) == false) {
itemOptions[opt.ItemId] = []
}
itemOptions[opt.ItemId].push([opt.OptName, opt.OptValue])
})
return itemOptions
});
}
getSearchTotalPurchaseItem(params) {
let clause = this.getSearchPurchaseItemClause(params)
delete clause.limit;
return db.purchaseItem.count(clause).then(cnt => cnt)
}
findPurchaseByOrgCodeAndPurchaseNo(params) {
let clause = { where: {} }
if (params.sword) {
clause.where.PurchaseNo = params.sword
}
if (params.orgCode) {
clause.where.OrgCode = params.orgCode
}
return db.purchase.findAll(clause).then(purchases => {
return purchases.map(p => p.Id)
})
}
replaceItemOption(itemId, itemOptions) {
return db.purchaseItemOption.destroy({ where: { ItemId: itemId } }).then(a => {
let options = itemOptions.map(opt => {
if(opt.optValue) {
return { ItemId: itemId, OptName: opt.optName, OptValue: opt.optValue }
}
})
return db.purchaseItemOption.bulkCreate(options).then(inserted => inserted.length > 0)
})
}
}
module.exports = new PurchaseComponent

View File

@@ -0,0 +1,20 @@
const service = require("../service/CrawlService")
, logger = require('logops');
class CrawlController {
getMethodName(req) {
return req.method.toLowerCase()
+ req.params.what.split('_').map(w => w.charAt(0).toUpperCase() + w.slice(1)).join('')
}
crawl(req, callback) {
let fn = this.getMethodName(req);
let params = Object.assign(req.body, req.query)
params = Object.assign(params, req.params)
logger.info('Invoking method TestService.%s', fn)
service[fn](params, callback)
}
}
module.exports = new CrawlController

View File

@@ -0,0 +1,20 @@
const purchase = require("../service/PurchaseService")
, logger = require('logops');
class PurchaseController {
getMethodName(req) {
return req.method.toLowerCase()
+ req.params.what.split('_').map(w => w.charAt(0).toUpperCase() + w.slice(1)).join('')
}
purchase(req, callback) {
let fn = this.getMethodName(req);
let params = Object.assign(req.body, req.query)
params = Object.assign(params, req.params)
logger.info('Invoking method PurchaseService.%s', fn)
purchase[fn](params, callback)
}
}
module.exports = new PurchaseController

85
src/model/IoBoundModel.js Normal file
View File

@@ -0,0 +1,85 @@
/* jshint indent: 2 */
module.exports = function (sequelize, DataTypes) {
return sequelize.define('ioBound', {
id: {
autoIncrement: true,
type: DataTypes.INTEGER(11).UNSIGNED,
allowNull: false,
primaryKey: true,
field: 'id'
},
IoType: {
type: DataTypes.STRING(2),
allowNull: false,
field: 'type'
},
ItemId: {
type: DataTypes.STRING(20),
allowNull: false,
field: 'pcode'
},
Barcode: {
type: DataTypes.STRING(30),
allowNull: false,
field: 'ean'
},
SerialNo: {
type: DataTypes.STRING(30),
allowNull: false,
field: 'serialno'
},
ArtNo: {
type: DataTypes.STRING(30),
allowNull: false,
comment: 'Article Number/PZN',
field: 'artno'
},
Qty: {
type: DataTypes.INTEGER(9).UNSIGNED,
allowNull: false,
comment: '실재고',
field: 'qty'
},
OrgCode: {
type: DataTypes.STRING(10),
allowNull: false,
field: 'c_code'
},
ShippingCode: {
type: DataTypes.STRING(30),
allowNull: false,
field: 'wcode'
},
BoxCode: {
type: DataTypes.STRING(30),
allowNull: false,
field: 'bcode'
},
CreatedBy: {
type: DataTypes.STRING(30),
allowNull: false,
field: 'reg_user'
},
CreatedAt: {
type: DataTypes.DATE,
allowNull: true,
field: 'regtime'
},
UpdatedBy: {
type: DataTypes.STRING(10),
allowNull: false,
field: 'update_user'
},
UpdatedAt: {
type: DataTypes.DATE,
allowNull: false,
field: 'update_time'
}
}, {
sequelize,
tableName: 'wms_in_out_bound',
freezeTableName: true,
timestamps: false
});
};

27
src/model/IoTypeModel.js Normal file
View File

@@ -0,0 +1,27 @@
/* jshint indent: 2 */
module.exports = function (sequelize, DataTypes) {
return sequelize.define('ioType', {
code: {
type: DataTypes.STRING(2),
allowNull: false,
primaryKey: true,
field: 'code'
},
Name: {
type: DataTypes.STRING(50),
allowNull: true,
field: 'name'
},
NameKr: {
type: DataTypes.STRING(50),
allowNull: true,
field: 'name_kr'
}
}, {
sequelize,
tableName: 'wms_in_out_type',
freezeTableName: true,
timestamps: false
});
};

38
src/model/Purchase.js Normal file
View File

@@ -0,0 +1,38 @@
/* jshint indent: 2 */
module.exports = function(sequelize, DataTypes) {
return sequelize.define('purchase', {
Id: {
type: DataTypes.INTEGER(11).UNSIGNED,
allowNull: false,
primaryKey: true,
autoIncrement: true,
field: 'seq'
},
OrgCode: {
type: DataTypes.STRING(10),
allowNull: true,
field: 'company_code'
},
PurchaseNo: {
type: DataTypes.STRING(50),
allowNull: false,
unique: true,
field: 'purchase_no'
},
Status: {
type: DataTypes.ENUM('발주요청'),
allowNull: false,
field: 'status'
},
CreatedAt: {
type: DataTypes.DATE,
allowNull: false,
field: 'created_at'
}
}, {
tableName: 'ibl_purchase',
freezeTableName: true,
timestamps: false
});
};

62
src/model/PurchaseItem.js Normal file
View File

@@ -0,0 +1,62 @@
/* jshint indent: 2 */
module.exports = function(sequelize, DataTypes) {
return sequelize.define('purchaseItem', {
Id: {
type: DataTypes.INTEGER(11).UNSIGNED,
allowNull: false,
primaryKey: true,
autoIncrement: true,
field: 'seq'
},
PurchaseId: {
type: DataTypes.INTEGER(11).UNSIGNED,
allowNull: false,
field: 'purchase_seq'
},
ItemLink: {
type: DataTypes.STRING(255),
allowNull: false,
field: 'item_link'
},
ItemName: {
type: DataTypes.STRING(50),
allowNull: false,
field: 'item_name'
},
ItemBrand: {
type: DataTypes.STRING(30),
allowNull: false,
field: 'item_brand'
},
ItemUnitPrice: {
type: DataTypes.DECIMAL,
allowNull: false,
field: 'item_unit_price'
},
ItemTax: {
type: DataTypes.ENUM('0','7','19','5','16'),
allowNull: false,
field: 'item_tax'
},
ItemCount: {
type: DataTypes.INTEGER(4),
allowNull: false,
field: 'item_count'
},
Status: {
type: DataTypes.ENUM('발주요청'),
allowNull: false,
field: 'status'
},
CreatedAt: {
type: DataTypes.DATE,
allowNull: false,
field: 'created_at'
}
}, {
tableName: 'ibl_purchase_item',
freezeTableName: true,
timestamps: false
});
};

View File

@@ -0,0 +1,23 @@
/* jshint indent: 2 */
module.exports = function(sequelize, DataTypes) {
return sequelize.define('purchaseItemOption', {
ItemId: {
type: DataTypes.INTEGER(11).UNSIGNED,
allowNull: false,
primaryKey: true
},
OptName: {
type: DataTypes.STRING(100),
allowNull: false
},
OptValue: {
type: DataTypes.STRING(100),
allowNull: false
}
}, {
tableName: 'ibp_purchase_itemopt',
freezeTableName: true,
timestamps: false
});
};

42
src/model/index.js Normal file
View File

@@ -0,0 +1,42 @@
'use strict';
const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
const basename = path.basename(__filename);
const args = require("../../config/Config")
const env = args.env || 'development';
const config = require('../../config/config.json')[env];
const db = {};
let sequelize;
if (config.use_env_variable) {
sequelize = new Sequelize(args.database, config.username, config.password, config);
} else {
sequelize = new Sequelize(config.database, config.username, config.password, config);
}
sequelize.authenticate().then(() => {
console.log('Connection has been established successfully.');
}).catch(err => {
console.error('Unable to connect to the database:', err);
process.exit(1)
});
fs.readdirSync(__dirname).filter(file => {
return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js');
}).forEach(file => {
const model = sequelize.import(path.join(__dirname, file));
db[model.name] = model;
});
Object.keys(db).forEach(modelName => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
db.sequelize = sequelize;
db.Sequelize = Sequelize;
module.exports = db;

View File

@@ -0,0 +1,38 @@
const logger = require("logops")
, HttpStatus = require('http-status-codes')
, cheerio = require('cheerio')
, puppeteer = require('puppeteer');
class CrawlService {
constructor() {
this.browser = null;
this.page = null;
}
async request(url) {
if (this.page == null) {
this.browser = await puppeteer.launch({ headless: true });
this.page = await this.browser.newPage();
}
await this.page.goto(url)
return this.page.evaluate(() => document.documentElement.outerHTML)
}
get(params, callback) {
this.request('https://www.amazon.de/').then(html => {
const $ = cheerio.load(html)
let selector = 'div.a-section.a-spacing-none.feed-carousel.first-carousel ul li a'
let links = $(selector).map((i, el) => {
return $(el).attr('href')
}).get()
callback(links)
})
}
}
module.exports = new CrawlService

View File

@@ -0,0 +1,103 @@
const db = require("../model")
, logger = require("logops")
, restClient = require('../component/RestClientComponent')
, HttpStatus = require('http-status-codes')
, purchaseComponent = require('../component/PurchaseComponent');
class PurchaseService {
response(res, callback) {
if (!res.code) res.code = HttpStatus.OK
if (!res.message) res.message = HttpStatus.getStatusText(res.code)
if (res.code) {
callback(res)
return;
}
callback({ code: HttpStatus.NOT_FOUND, message: HttpStatus.getStatusText(HttpStatus.NOT_FOUND) })
}
post(params, callback) {
db.purchase.findAll({
where: { PurchaseNo: params.itemData[0].purchaseNo }
}).then(result => {
if (result.length) {
logger.error('Purchase No. Duplicated %s', JSON.stringify(params))
callback({ code: HttpStatus.CONFLICT, message: HttpStatus.getStatusText(HttpStatus.CONFLICT) })
} else {
let now = new Date();
db.purchase.create(purchaseComponent.getPurchaseData(params.itemData[0], now)).then(purchase => {
db.purchaseItem.bulkCreate(purchaseComponent.getPurchaseItemData(params.itemData, purchase, now)).then(createdItems => {
let itemOptions = []
createdItems.map((created, k) => {
params.itemData[k].itemOptions.map(opt => {
if (opt.optValue) {
itemOptions.push({
ItemId: created.Id,
OptName: opt.optName,
OptValue: opt.optValue
})
}
})
})
db.purchaseItemOption.bulkCreate(itemOptions).then(result => {
callback(result.length ? { inserted: createdItems.map(item => item.Id) } : { inserted: [] })
})
})
})
}
})
}
put(params, callback) {
let itemOptions = params.ItemOptions;
delete params.ItemOptions
Promise.all([
db.purchaseItem.update(params, { where: { Id: params.Id } }).then(updated => updated > 0),
purchaseComponent.replaceItemOption(params.Id, itemOptions)
]).then(results => {
logger.info('Update purchase promise results - %s', JSON.stringify(results))
let code = results.filter(result => result == true).length ? HttpStatus.OK : HttpStatus.NOT_MODIFIED
callback({ code: code, message: HttpStatus.getStatusText(code) })
})
}
async getSearch(params, callback) {
if (params.sword || params.orgCode) {
params.purchaseId = await purchaseComponent.findPurchaseByOrgCodeAndPurchaseNo(params);
}
let clause = purchaseComponent.getSearchPurchaseItemClause(params)
if (Object.keys(clause.where).length) {
db.purchaseItem.findAll(clause).then(rows => {
let responseBody = { code: HttpStatus.NOT_FOUND, message: HttpStatus.getStatusText(HttpStatus.NOT_FOUND) }
if (rows.length) {
Promise.all([
purchaseComponent.getSearchTotalPurchaseItem(params),
purchaseComponent.findPurchaseById(rows.map(row => row.PurchaseId)),
purchaseComponent.findPurchaseItemOptionByItemId(rows.map(row => row.Id))
]).then(results => {
let total = results[0]
let purchases = results[1];
let itemOptions = results[2];
rows.forEach((row, k) => {
rows[k].PurchaseNo = purchases[row.PurchaseId].PurchaseNo
rows[k].OrgCode = purchases[row.PurchaseId].OrgCode
rows[k].ItemOptions = itemOptions[row.Id]
})
responseBody = { code: HttpStatus.OK, message: HttpStatus.getStatusText(HttpStatus.OK), data: { total: total, rows: rows } }
this.response(responseBody, callback)
})
} else {
this.response(responseBody, callback)
}
});
} else {
logger.debug('Clause has no where statement - %s', JSON.stringify(clause))
this.response({
code: HttpStatus.BAD_REQUEST,
message: HttpStatus.getStatusText(HttpStatus.BAD_REQUEST)
}, callback)
}
}
}
module.exports = new PurchaseService

View File

@@ -0,0 +1,92 @@
const fetch = require("node-fetch")
, logger = require("logops");
class RestClientService {
constructor() {
this.token = null
this.emptyResponse = { code: 200, data: null }
this.localhost = 'http://localhost:31000/api/v1/'
this.clientId = 'F8Nbz9gGUvLgdn8T'
this.clientSecret = 'Fesmx7hHCCMx7Cby7FhV2fAtf2NYEFzP5fCKuwEEdpf8hpnsnnQn9qYhNHt6SsDD'
this.setToken()
}
setToken() {
this.token = null
return fetch(this.localhost + 'oauth/token?client_id=' + this.clientId + '&grant_type=client_credentials&client_secret=' + this.clientSecret, {
method: 'GET',
headers: {
'content-type': 'application/json'
}
}).then(res => res.json()).then(res => {
logger.debug(res, 'Tracking service got app token successfully')
this.token = res.access_token
return this.token
})
}
getHeader(additionalheaders) {
let headers = {
"Authorization": "Bearer " + this.token,
"Content-Type": "application/json"
}
return additionalheaders ? Object.assign(headers, additionalheaders) : headers
}
getResponse(data) {
if (data.code == 406) {
logger.info(data, 'Token expired and requesting new token')
this.emptyResponse.tokenPromise = this.setToken();
return this.emptyResponse
}
return data;
}
getProductBrandByItemId(params) {
return fetch(this.localhost + 'catalog/brand', {
method: 'OPTIONS',
headers: this.getHeader(),
body: JSON.stringify(params)
}).then(res => res.json()).then(data => this.getResponse(data))
}
getProductByBrand(params) {
return fetch(this.localhost + 'catalog/brand/' + params.brand, {
method: 'GET',
headers: this.getHeader()
}).then(res => res.json()).then(data => this.getResponse(data))
}
getParcel(params) {
if (this.token == null) return this.emptyResponse
let defaultParams = {
"request": "get", "column": ["ShippingCode"],
"status": [2], "limit": 1, "offset": 0, "groupby": ["ShippingCode"], "order": [['CreatedAt', 'DESC']],
'daterangeby': 'ExportedAt',
'daterange': {
sdate: (function () {
let d = new Date();
d.setMonth(d.getMonth() - 1);
return d.toLocaleDateString();
})(),
edate: (function () {
let d = new Date();
d.setDate(d.getDate() + 2);
return d.toLocaleDateString();
})()
}
}
Object.assign(defaultParams, params)
logger.debug(defaultParams, 'Request parcel service params')
return fetch(this.localhost + 'parcel', {
method: 'POST',
headers: this.getHeader(),
body: JSON.stringify(defaultParams)
}).then(res => res.json()).then(data => this.getResponse(data))
}
}
module.exports = new RestClientService;