I am using the oracledb package to retrieve some data and output the data as json and I have successfully done that but I want the values to be in quotes for example this is the output i get.
{
"postage_charge":0,
"shipping_charge":52.28,
"order_processing":9.82,
"receiving_charge":0,
"storage_charge":21.36,
"product_charge":2.65,
"sup_charge":0,
"hold_charge":0
}
I want it too look like
{
"postage_charge":"0",
"shipping_charge":"52.28",
"order_processing":"9.82",
"receiving_charge":"0",
"storage_charge":"21.36",
"product_charge":"2.65",
"sup_charge":"0",
"hold_charge":"0"
}
here is my code
async function selectInvoiceDetail(req, res, invoice) {
try {
connection = await oracledb.getConnection({
user: "",
password: "",
connectString: "192.168.1.5:1521/test"
});
postageCharge = await connection.execute(`select sum(item_total) as postal_charge from INVOICE_ITEMS where INVOICE_ID='${invoice}' and charge_type='SHIPPING' and charge_subtype='POSTAGE'`);
shippingCharge = await connection.execute(`select sum(item_total) as shipping_charge from INVOICE_ITEMS where INVOICE_ID='${invoice}' and (charge_type='SHIPPING' and charge_subtype='SHIPPING' or charge_type='SUP' and charge_subtype='DUTAX' or charge_type='SUP' and charge_subtype='SHIPPING' or charge_type='SUP' and charge_subtype='VASSHIP')`);
orderProcessing = await connection.execute(`select sum(item_total) as order_charge from INVOICE_ITEMS where INVOICE_ID='${invoice}' and (charge_type='ORDERS' and charge_subtype='BASE' or charge_type='ORDERS' and charge_subtype='INTNAT' or charge_type='ORDERS' and charge_subtype='LTLCP' or charge_type='ORDERS' and charge_subtype='PACKAGING' or charge_type='ORDERS' and charge_subtype='PIECE' or charge_type='ORDERS' and charge_subtype='PIECEC' or charge_type='ORDERS' and charge_subtype='SERIAL' or charge_type='SUP' and charge_subtype='ORDERS')`);
receivingCharge = await connection.execute(`select sum(item_total) as receiving_charge from INVOICE_ITEMS where INVOICE_ID='${invoice}' and (charge_type='RECEIPT' and charge_subtype='PIECE' or charge_type='RECEIPT' and charge_subtype='ITEM' or charge_type='RECEIPT' and charge_subtype='PIECEC' or charge_type='SUP' and charge_subtype='RECEIVE' or charge_type='RECEIPT' and charge_subtype='LEVEL')`);
storageCharge = await connection.execute(`select sum(item_total) as storage_charge from INVOICE_ITEMS where INVOICE_ID='${invoice}' and (charge_type='STORAGE' and charge_subtype='FLAT' or charge_type='STORAGE' and charge_subtype='LOCATION' or charge_type='STORAGE' and charge_subtype='VOLUME')`);
productCharge = await connection.execute(`select sum(item_total) as product_charge from INVOICE_ITEMS where INVOICE_ID='${invoice}' and charge_type='PRODUCT' and charge_subtype='SETUP'`);
supCharge = await connection.execute(`select sum(item_total) as sup_charge from INVOICE_ITEMS where INVOICE_ID='${invoice}' and (charge_type='SUP' and charge_subtype='RECEIPT' or charge_type='SUP' and charge_subtype='CRETURN' or charge_type='SUP' and charge_subtype='LABEL' or charge_type='SUP' and charge_subtype='RETURN' or charge_type='SUP' and charge_subtype='VAS')`);
holdCharge = await connection.execute(`select sum(item_total) as hold_charge from INVOICE_ITEMS where INVOICE_ID='${invoice}' and charge_type='OHOLD' and charge_subtype='PERCENT'`);
} catch (err) {
return res.send(err.message);
} finally {
if (connection) {
try {
await connection.close();
} catch (err) {
console.error(err.message);
}
}
res.setHeader('Content-Type', 'application/json');
var result = {
"postage_charge": postageCharge.rows[0].POSTAL_CHARGE ?? 0,
"shipping_charge": shippingCharge.rows[0].SHIPPING_CHARGE ?? 0,
"order_processing": orderProcessing.rows[0].ORDER_CHARGE ?? 0,
"receiving_charge": receivingCharge.rows[0].RECEIVING_CHARGE ?? 0,
"storage_charge": storageCharge.rows[0].STORAGE_CHARGE ?? 0,
"product_charge": productCharge.rows[0].PRODUCT_CHARGE ?? 0,
"sup_charge": supCharge.rows[0].SUP_CHARGE ?? 0,
"hold_charge": holdCharge.rows[0].HOLD_CHARGE ?? 0
};
return res.send(result);
}
}
any help is appreciated
thank you.
Just convert number (coming from DB) to string .toString().
In you results :(postageCharge.rows[0].POSTAL_CHARGE ?? 0).toString() and the rest of them which type is number.
<!DOCTYPE html>
<html>
<body>
<h2>convert numbers coming from server to string to get quotes in JSON - toString() Method</h2>
<p>toString() returns the content of a string:</p>
<p> your example woudl be : (postageCharge.rows[0].POSTAL_CHARGE ?? 0).toString(),</p>
<p id="demo"></p>
<script>
//your example woudl be
// (postageCharge.rows[0].POSTAL_CHARGE ?? 0).toString(),
let fromServer = 123;
let result = fromServer.toString();
document.getElementById("demo").innerHTML = result;
</script>
</body>
</html>
number toString Mozilla documentation
Read the node-oracledb manual on Fetching Numbers and Dates as String.
Try something like:
sql = `SELECT 12.23 AS D FROM DUAL WHERE 1 = :i`;
binds = [1];
options = { fetchInfo: { 'D': { type:oracledb.STRING }} };
result = await connection.execute(sql, binds, options);
console.dir(result, { depth: null });
The advantage of this method over converting with toString() is that it circumvents Oracle's internal decimal format being converted to Node.js floating point type and removes any subsequent user confusion about the numbers not matching.
I included a bind variable in the WHERE clause as an example since you must change your usage of ... where INVOICE_ID='${invoice}' ... to use binding. This is important for scalability and security.
An alternative to fetchInfo is to do the conversion in the SQL statement e.g. like
SELECT TO_CHAR(12.23) AS D FROM DUAL WHERE 1 = :i
Since you have a fixed number of SELECT statements and they return simple types, you should consider wrapping them all in a single PL/SQL block. This will reduce Database Round-trips because you only need one execute() and it will make the overall system more efficient. You can do something like:
const oracledb = require('oracledb');
const dbConfig = { user: 'cj', password: process.env.NODE_ORACLEDB_PASSWORD, connectString: 'localhost/orclpdb1' };
if (process.platform === 'darwin') {
oracledb.initOracleClient({libDir: process.env.HOME + '/Downloads/instantclient_19_8'});
}
const plsql = `begin
select sum(sal) into :salsum from emp where empno > :en;
select sum(comm) into :comsum from emp where empno > :en;
end;`;
const binds = {
en: 7600,
salsum: {dir: oracledb.BIND_OUT, type: oracledb.STRING},
comsum: {dir: oracledb.BIND_OUT, type: oracledb.STRING}
};
const options = { outFormat: oracledb.OUT_FORMAT_OBJECT };
async function run() {
let connection;
try {
connection = await oracledb.getConnection(dbConfig);
const result = await connection.execute(plsql, binds, options);
console.dir(result.outBinds, { depth: null });
} catch (err) {
console.error(err);
} finally {
if (connection) {
try {
await connection.close();
} catch (err) {
console.error(err);
}
}
}
}
run();
Related
I have been using rethinkdb, and since it's getting outdated, i wanted to switch to mongodb. On my prefix command, i keep on getting that error and this is my code:
const { Guild } = require('../../models/Guild');
async function prefixCommand (msg, args) {
if (!msg.member.permissions.has('manageGuild') && !this.config.options.devs.includes(msg.author.id)) {
return msg.channel.createMessage('You need `manageGuild` to be able to use this command!');
}
Guild.findOne({ guildID: msg.channel.guild.id }, function(err, doc) {
let prefixConfig;
if (!args[0]) {
return msg.channel.createMessage('Prefix is a required argument!\nUsage: `prefix <prefix>`');
}
if (args.join(' ').length > 32) {
return msg.channel.createMessage(`Your prefix cannot be over 30 characters long! You are ${args.join(' ').length - 32} characters over the limit.`);
}
if (doc.prefix === args.join(' ').toLowerCase()) {
return msg.channel.createMessage(`\`${args[0]}\` is already your current prefix.`);
}
//prefixConfig.prefix = args.join(' ');
doc.prefix = args.join(' ');
doc.save();
//await this.m.updateGuild(msg.channel.guild.id, prefixConfig.prefix);
msg.channel.createMessage(`Prefix has been set to \`${prefixConfig}\``);
});
}
While Guild is this:
const mongoose = require('mongoose');
const guildSchema = new mongoose.Schema({
guildID: String,
guildName:String,
ownerID: String,
prefix: {
type: String,
default: '>'
}
});
module.exports = mongoose.model('Guild', guildSchema)
I can't seem to figure out what's the problem. Any help is appreciated!
Just change your require to const Guild = require('../../models/Guild');
You are exporting model as a default from /models/Guild but require it as if its named export like module.exports = { Guild }
I am trying to accomplish synchronisation in Mongoose query inside a _.each lodash function like this -
let commentContainer = [];
let comments = {..} //json object having comments
_.each(comments, comment => {
User.findOne({_id: comment.createdBy}).exec()
.then(function(commentor){
var c = {
text: comment.text,
votes: comment.votes.length,
commentor: {
name: commentor.name,
profilePhoto: commentor.profilePhoto,
id: commentor._id
}
}
commentContainer.push(c);
});
});
}
console.log(commentContainer); //it shows []
How can I achieve it, I tried using setTimeout function by giving a delay but it does not seems a valid procedure.
modify your code like this way:
let fun = async() => {
let commentContainer = [];
let comments = {..} //json object having comments
await _.each(comments, comment => {
User.findOne({_id: comment.createdBy}).exec()
.then(function(commentor){
var c = {
text: comment.text,
votes: comment.votes.length,
commentor: {
name: commentor.name,
profilePhoto: commentor.profilePhoto,
id: commentor._id
}
}
commentContainer.push(c);
});
});
}
console.log(commentContainer); //it shows []
}
make your function async and use await keywoed when you need to wait for the process to complete before next iteration
It's because Node.js is asynchronous.You should use async/await or promise or callback when you are dealing with non-blocking call like DB-call or Http client call.
let comments = {..} //json object having comments
console.log(findUSer(comments)); // print result
async function findUSer(comments){
let commentContainer = [];
await _.each(comments, comment => {
User.findOne({_id: comment.createdBy}).exec()
.then(function(commentor){
var c = {
text: comment.text,
votes: comment.votes.length,
commentor: {
name: commentor.name,
profilePhoto: commentor.profilePhoto,
id: commentor._id
}
}
commentContainer.push(c);
});
});
}
return commentContainer;
}
i'm facing a issue with my unit test, stuck completely, the code is simple, please need to understand what's going on, my stub is never called, the set seems to be correct, here the code:
let strategy = fixtures.load('strategy')
chai.use(chaiAsPromised)
describe.only('Spawn Order Job', () => {
let getPositionsStub, createJobStub, daoStub,sandbox
beforeEach(()=>{
sandbox = sinon.createSandbox()
daoStub = sandbox.stub(dao, 'updateActiveOrders').resolves(true) //async
getPositionsStub = sandbox.stub(strategyModule, 'getPositions') //sync
createJobStub = sandbox.stub(helpers, 'createJob') //sync
createJobStub.returns(true)
getPositionsStub.resolves([{fake:'t'}, {fake:'t'}])
})
afterEach(()=>{
sandbox.restore()
})
//OK
it('Should failed with no param, type error context', ()=> {
const promise = spawnOrderJob()
expect(promise).to.be.rejectedWith(TypeError)
})
//OK
it('Should throw error timeout order', () => {
getPositionsStub.resolves([{fake:'t'}, {fake:'t'}])
strategy.lastDateOrder = new Date()
const ctx = { state: {strategy, dashboard, position:null}}
const action = {b: true, s: false}
const promise = spawnOrderJob(action, ctx)
expect(getPositionsStub.called).to.be.true
expect(daoStub.called).to.be.false
expect(createJobStub.called).to.be.false
expect(promise).to.be.rejectedWith(ORDER_ERROR, 'Timeout between order not expired.')
})
//KO stub never called
it.only('Should pass validation on buy', () => {
strategy.lastDateOrder = 0
const ctx = { state: {strategy, dashboard, position: null }}
const action = {b: true, s: false}
const promise = spawnOrderJob(action, ctx)
expect(promise).to.be.fulfilled
expect(getPositionsStub.called).to.be.true //ok
expect(createJobStub.called).to.be.true //never callled ????
expect(daoStub.called).to.be.true //never called ????
})
})
Want to understand what's going now there, the call are correct imo, running with mocha 5.2
Helpers.js : function is described as follow:
async function spawnOrderJob(action, ctx) {
try {
const { strategy, dashboard, position } = ctx.state
const {b, s} = action
//check in case strategy context
if (strategy) {
//pass validation buy contnext
if (b) {
//this stub is working
const positions = await strategyModule.getPositions(ctx)
const { maxPosition } = strategy.allocatedBTC
const { activeOrders, maxActiveOrders, timeBetweenOrder, lastDateOrder } = strategy
debug('Active orders:', strategy.activeOrders)
debug('Position:', positions.length)
if (activeOrders >= maxActiveOrders)
throw new ORDER_ERROR('Max active orders reach.')
if (positions.length + activeOrders >= maxPosition)
throw new ORDER_ERROR('Max positions reach.')
if (!timeoutExpired(lastDateOrder, timeBetweenOrder))
throw new ORDER_ERROR('Timeout between order not expired.')
//increment active orders counter
//stub fail, but not called at all
await dao.updateActiveOrders(strategy, true)
}
//Sell context
if (s) {
if (!position)
throw new ORDER_ERROR('No position to sell')
}
}
//stub fail, but called internally
return createJob(constants.DASHBOARD_CREATE_ORDER, {
orderType: b ? 'BUY' : 'SELL',
title: `Strategy create order ( ${ b ? 'BUY' : 'SELL'} )`,
strategy,
dashboard,
position
})
} catch (e) {
throw e
}
}
function createJob(name, data){
//shortcut queue.create (kue.js)
return queue.c(name,data)
}
module.exports = {
createJob,
spawnOrderJob
}
DAO
const updateActiveOrders = async (strategy, increment) => {
try {
const s = await model.findOne({_id: strategy._id})
if (!s) throw new Error('Strategy not found.')
s.activeOrders = increment ? s.activeOrders+1 :s.activeOrders-1
s.lastDateOrder = new Date()
return await s.save()
}catch(e){
throw e
}
}
module.exports = {updateActiveOrders}
I'm trying to use transaction inside forEach loop using async/await syntax of Node 7.0+
When I try to print committed transaction response in console, I'm able to see the values but those same values are not committed in to DB.
Below is the code :
documentInfo.forEach(async (doc) => { // array of documentInfo
var frontImgName = await module.exports.uploadImage(docFiles, doc.front, req, res )
var backImgName = await module.exports.uploadImage(docFiles, doc.back, req, res )
var checkKycDoc = await KYCDocument.findOne({
where: {
kyc_id: checkUserKyc.dataValues.kyc_id,
user_id: checkUserKyc.dataValues.user_id
}
})
if (checkKycDoc) { //update
var updateDocument = await KYCDocument.update({
document_name: doc.document_name,
front_image: frontImgName,
back_image: backImgName
}, {
where: {
kyc_id: checkUserKyc.dataValues.kyc_id,
user_id: checkUserKyc.dataValues.user_id
},
}, {transaction})
log('updateDocument', updateDocument.dataValues)
} else { // insert
var newKycDocument = await new KYCDocument({
kyc_id: checkUserKyc.dataValues.kyc_id,
user_id: checkUserKyc.dataValues.user_id,
document_name: doc.document_name,
front_image: frontImgName,
back_image: backImgName,
status: true
}, {transaction})
log('newKycDocument', newKycDocument.dataValues)
}
if (rowCount === documentInfo.length) {
await transaction.commit() // transaction is printed on this line
log('KYC has been uploaded successfully')
helpers.createResponse(res, constants.SUCCESS,
messages.KYC_UPLOAD_SUCCESS,
{'error': messages.KYC_UPLOAD_SUCCESS}
)
} else {
rowCount++
}
})
The issue was in the create method.
To resolve the issue I had to create a new row using:
var newKycDocument = await KYCDocument.create({
kyc_id: checkUserKyc.dataValues.kyc_id,
user_id: checkUserKyc.dataValues.user_id,
document_name: doc.document_name,
front_image: frontImgName,
back_image: backImgName
}, {transaction})
I was missing the .create method.
I have a function,
var findUserDevice = function(userDeviceId){
var device = db.DeviceUser.find({
where: {
id: userDeviceId
}
}).then(function(device) {
if (!device) {
return 'not find';
}
return device.dataValues;
});
};
but this function does not return anything...
var UserDevice = findUserDevice(req.body.deviceUserId);
console.log(UserDevice);// undefined
The operation you are trying to do is async, which means that you need to use a callback. Since sequelize is build on top of Promises, you should actually write your code like this :
var findUserDevice = function(userDeviceId){
// return the promise itself
return db.DeviceUser.find({
where: {
id: userDeviceId
}
}).then(function(device) {
if (!device) {
return 'not find';
}
return device.dataValues;
});
};
And later use it like :
findUserDevice(req.body.deviceUserId).then( function(UserDevice) {
console.log(UserDevice);
});
It's 2020, async & await are becoming more popular. You can change your code to:
const findUserDevice = async function (userDeviceId) {
const device = await db.DeviceUser.findOne({
where: {
id: userDeviceId
}
});
if (device === null) {
return 'device not found';
}
return device.dataValues;
};
(async () => {
// ...
const UserDevice = await findUserDevice(req.body.deviceUserId);
console.log(UserDevice);
// ...
})()
IMHO, the code above is way more readable.
If you are getting undefined instead of 'not find' on the console, it means your function is returning a value. The problem might be dataValues is actually undefined. You need to check for the content of device.
Hint: Try returning just device or device.id
PS. If you want to do the search based on id, should go for findById() function of your model.
var device = db.DeviceUser.findById(userDeviceId).then(function(device) {
if (!device) {
return 'not find';
}
return device.dataValues;
});
This function received params id, this worker for me:
const { customer } = require('../models');
const get = async function(req, res){
let id = req.params.id;
[err, singleCustomer] = await to(customer.findByPk(id, { raw : true }));
return ReS(res, { message :'Obtener cliente: : ', data : JSON.stringify(singleCustomer) });
}