Can't I use the req.user inside promises in nodejs? - node.js

I am trying to do the stripe payment using nodejs and I am getting the following errors. One in console and one in web app UI in the browser. What are the reasons?
Also I am trying to use req.user property details which are saved in mongoDB.
I am getting the console error as : (node:6344) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'subscriptionPlan' of undefined
and on browser =>
Error: You cannot use a Stripe token more than once: tok_1IJggu*******************.
Below is my code:
router.post('/processPayment/:priceID', (req, res) => {
console.log("plan Token = "+ req.body.stripeToken);
console.log("plan Email = "+ req.body.stripeEmail);
var dateFormated, dateFormated2;
return stripe2.customers.create({
source: req.body.stripeToken,
email: req.body.stripeEmail
}).then(customer => {
stripe2.subscriptions.create({
customer: customer.id,
items: [
{
plan: req.params.priceID
}
]
}).then(subscription => {
console.log("subscription.status = "+ subscription.status);
dateFormated = new Date();
dateFormated2 = new Date();
console.log(dateFormated2.getMinutes() +' '+dateFormated2.getHours()+' '+dateFormated2.getDate() + ' * *');
var j = schedule.scheduleJob(dateFormated2.getMinutes() +' '+dateFormated2.getHours()+' '+dateFormated2.getDate() + ' * *',function(){
var snm = new Date();
return stripe2.subscriptions.retrieve(req.user.subsID)
.then(subsData => {
console.log("Status = "+ subsData.status);
if(subsData.status == 'active')
{
User.findOneAndUpdate({_id:req.user.id},
{$set: {"subscriptionDuplicateDate":req.user.subscriptionNextMonth }},
function (error, data) {
if (error) {
console.log(error);
return res.render("error",{error:error});
}
else if(req.user.subscriptionPlan == '$299' || req.user.subscriptionPlan == '$499' || req.user.subscriptionPlan == '$999')
{
snm = snm.setMonth(snm.getMonth() + 1);
console.log("snm = "+ snm);
User.findOneAndUpdate({_id:req.user.id},
{$set: {"subscriptionNextMonth" : new Date(snm.toLocaleString())}},
function (error, data) {
if (error) {
console.log(error);
return res.render("error",{error:error});
}
})
console.log('Your scheduled job every month');
}
else if(req.user.subscriptionPlan == '$2990' || req.user.subscriptionPlan == '$4990' || req.user.subscriptionPlan == '$9990')
{
snm = snm.setFullYear(snm.getFullYear() + 1);
console.log("snm = "+ snm);
User.findOneAndUpdate({_id:req.user.id},
{$set: {"subscriptionNextMonth" : new Date(snm.toLocaleString())}},
function (error, data) {
if (error) {
console.log(error);
return res.render("error",{error:error});
}
})
console.log('Your scheduled job every year');
}
})
}
else {
User.findOneAndUpdate({_id:req.user.id},
{$set: {"subscriptionTotalCount" : 0}},
function (error, data) {
if (error) {
console.log(error);
return res.render("error",{error:error});
}
})
}
}).catch(err => {
res.render('error', {message: err});
});
});
if(req.user.subscriptionPlan == '$299' || req.user.subscriptionPlan == '$499' || req.user.subscriptionPlan == '$999')
{
User.findOneAndUpdate({_id:req.user.id},
{$set: {"subscriptionDate":dateFormated,
"subscriptionDuplicateDate":dateFormated,
"subscriptionNextMonth":new Date(dateFormated.setMonth(dateFormated.getMonth() + 1))}},
function (error, data) {
if(data)
console.log("subscription date set");
})
}
else if(req.user.subscriptionPlan == '$2990' || req.user.subscriptionPlan == '$4990' || req.user.subscriptionPlan == '$9990')
{
User.findOneAndUpdate({_id:req.user.id},
{$set: {"subscriptionDate":dateFormated,
"subscriptionDuplicateDate":dateFormated,
"subscriptionNextMonth":new Date(dateFormated.setFullYear(dateFormated.getFullYear() + 1))}},
function (error, data) {
if(data)
console.log("subscription date set");
})
}
// console.log("subscription.items = "+ JSON.stringify(subscription.items));
console.dir(subscription);
res.redirect('/thankyou/0d4a3bc9cd71c4500584f01e7ce74cc6f2a4967ca266f3b7578ff29bd640dbbc/'+customer.id+'/'+subscription.id);
})
}).catch(err => {
res.render('error', {message: err});
});
});

Related

Node JS for loop inserting data twice

I am trying import the contacts in a database but sometime its inserting records 2 times. Requirement is, If the number is already exist it should get updated otherwise inserted as a new row. I am using MySQL database.
I am using for loop with async.
var numbers = {
numbers:[
{
name:"A",
number:9876543211
},
{
name:"B",
number:7876543211
},
{
name:"C",
number:9886543211
},
{
name:"D",
number:8876543211
}
]
};
async.forEachOf(numbers, (numberObj, key, callback) => {
var createdAt = moment.utc().valueOf();
var updatedAt = moment.utc().valueOf();
gfs.checkContact(userInfo.user_id, code, numberObj.number, function(contactInfo, err){
if(err){
response.error = "sorry";
res.send(response); return false;
}else{
if (contactInfo.length > 0) {
gfs.qry("UPDATE contacts SET fullName='"+numberObj.name+"', updatedAt='"+updatedAt+"' WHERE cid='"+contactInfo[0].cid+"'").then(function (results){
}).catch(function (errorMessage){
})
}else{
gfs.qry("INSERT INTO contacts(user_id, fullName, code, mobile, createdAt, updatedAt) VALUES('"+userInfo.user_id+"', '"+numberObj.name+"', '"+code+"', '"+numberObj.number+"', '"+createdAt+"', '"+updatedAt+"')").then(function (results){
}).catch(function (errorMessage){
})
}
}
callback();
});
}, err => {
if (err){
response.error = "sorry";
res.send(response);
}else{
response.success = "success";
response.numbers = numbers;
res.send(response);
}
});
I want to insert the contact number if it's not exist in the database for logged-in user id or it should get update the other fields like name, updated at if number already in database for the logged-in user id.
The callback needs to be inside the .thens or .catches.
async.forEachOf(numbers, (numberObj, key, callback) => {
var createdAt = moment.utc().valueOf();
var updatedAt = moment.utc().valueOf();
gfs.checkContact(userInfo.user_id, code, numberObj.number, function (contactInfo, err) {
if (err) {
return callback(err);
} else {
if (contactInfo.length > 0) {
gfs.qry("UPDATE contacts SET fullName='" + numberObj.name + "', updatedAt='" + updatedAt + "' WHERE cid='" + contactInfo[0].cid + "'")
.then(function (results) {
return callback(null, true);
}).catch(function (errorMessage) {
return callback(errorMessage);
})
} else {
gfs.qry("INSERT INTO contacts(user_id, fullName, code, mobile, createdAt, updatedAt) VALUES('" + userInfo.user_id + "', '" + numberObj.name + "', '" + code + "', '" + numberObj.number + "', '" + createdAt + "', '" + updatedAt + "')")
.then(function (results) {
return callback(null, true);
}).catch(function (errorMessage) {
return callback(errorMessage);
})
}
}
});
}, err => {
if (err) {
response.error = "sorry";
res.send(response);
} else {
response.success = "success";
response.numbers = numbers;
res.send(response);
}
});
Note: in your function gfs.checkContact the callback signature is (contactInfo, err). Which is reverse of what Node.js standard. Node uses err, callback or err, data.
EDIT1:
Also, .forEachOf iterates object like Object.keys. In your case there is only one key called numbers.
So, the numberObj will contain:
[ { name: 'A', number: 9876543211 },
{ name: 'B', number: 7876543211 },
{ name: 'C', number: 9886543211 },
{ name: 'D', number: 8876543211 } ]
And numberObj.name will be undefined.
You probably want
async.each(numbers.numbers, ...)
I have changed my code, now using promise. It's working fine now.
var numbers = [
{
name:"A",
number:9876543211
},
{
name:"B",
number:7876543211
},
{
name:"C",
number:9886543211
},
{
name:"D",
number:8876543211
}
];
async.forEachOf(numbers, (numberObj, key, callback) => {
var createdAt = moment.utc().valueOf();
var updatedAt = moment.utc().valueOf();
gfs.checkContactPromise({
user_id:userInfo.user_id,
code:code,
mobile:numberObj.number,
fullName:numberObj.name,
createdAt:createdAt,
updatedAt:updatedAt
}).then( function (addContactQry){
gfs.qry(addContactQry).then(function (results){
userContacts.push("'"+numberObj.number+"'");
callback();
}).catch(function (errorMessage){
callback();
})
}).catch( function (errorMessage){
callback();
});
}, err => {
if (err){
response.error = "sorry";
res.send(response);
}else{
response.success = "success";
response.numbers = numbers;
res.send(response);
}
});

Unable to retrive data and push inside loop in node js

I am trying to retrieve attendance list along with user details.
I am using caminte.js(http://www.camintejs.com/) Cross-db ORM for database interaction.
Here is my code sample of model function "attendanceList".
exports.attendanceList = function (req, callback) {
var query = req.query;
var searchfilters = {};
if(!req.user){
callback({ code:400, status:'error', message: 'Invalid Request', data:{}});
}else{
searchfilters["vendor_id"] = parseInt(req.user._id);
}
if(query.location && parseString(query.location) != '') {
searchfilters["location"] = parseString(query.location);
}
if (query.device_details && parseString(query.device_details) != '') {
searchfilters["device_details"] = parseString(query.device_details);
}
if(query.created_on) {
searchfilters["created_on"] = query.created_on;
}
if(query.status) {
searchfilters["status"] = { regex: new RegExp(query.status.toLowerCase(), "i") };
}
var SkipRecord = 0;
var PageSize = 10;
var LimitRecord = PageSize;
var PageIndex = 1;
if(query.pagesize) {
PageSize = parseInt(query.pagesize);
}
if(query.pageindex) {
PageIndex = parseInt(query.pageindex);
}
if (PageIndex > 1) {
SkipRecord = (PageIndex - 1) * PageSize;
}
LimitRecord = PageSize;
var SortRecord = "created_on";
if(query.sortby && query.sorttype) {
var sortingBy = query.sortby;
var sortingType = 'ASC';
if(typeof query.sorttype !== 'undefined') {
sortingType = query.sorttype;
}
SortRecord = sortingBy + ' ' + sortingType;
}
Attendance.find({ where: searchfilters, order: SortRecord, limit: LimitRecord, skip: SkipRecord }, async function (err, result) {
if(err){
callback({ code:400, status:'error', message:'Unable to connect server', errors:err });
} else {
await result.map(function(row, i){
User.findById(parseInt(row.user_id), function(err, data){
if(err){
console.log(err);
} else {
result[i]['userDetails'] = data;
}
});
});
await Attendance.count({ where: searchfilters }, function (err, count) {
callback({ code:200, status:'success', message:'OK', total:count, data:result });
});
}
});
};
I am getting only attendance list without user details. How do I force to push user details into attendance list? Any Help!!
Thank You
This behavior is asynchronous. When you're making request to DB, your code keeps running, while task to get data comes to task queue.
To keep things simple, you need to use promises while handling asynchronous jobs.
Rewrite your code from this:
Attendance.find({ where: searchfilters, order: SortRecord, limit: LimitRecord, skip: SkipRecord }, async function (err, result) {
if(err){
callback({ code:400, status:'error', message:'Unable to connect server', errors:err });
} else {
await result.map(function(row, i){
User.findById(parseInt(row.user_id), function(err, data){
if(err){
console.log(err);
} else {
result[i]['userDetails'] = data;
}
});
});
await Attendance.count({ where: searchfilters }, function (err, count) {
callback({ code:200, status:'success', message:'OK', total:count, data:result });
});
}
});
To this:
const findAttendanceFirst = (searchFilters, SortRecord, LimitRecord, SkipRecord) => {
return new Promise((resolve, reject) => {
Attendance.find({ where: searchFilters, order: SortRecord, limit: LimitRecord, skip: SkipRecord }, (err, result) => {
if(err) return reject(err);
resolve(result);
});
});
}
const findUserByIdForUserDetails = (userId) => {
return new Promise((resolve, reject) => {
User.findById(parseInt(userId), function(err, data){
if(err) return reject(err);
resolve(data);
})
});
}
const getAttendanceCount = (searchFilters) => {
return new Promise((resolve, reject) => {
Attendance.count({ where: searchFilters }, (err, count) => {
if(err) return reject(err);
resolve(count);
});
})
}
So, now we can use this separate functions to make async behavior looks like sync.
try {
const data = await findAttendanceFirst(searchFilters, SortRecord, LimitRecord, SkipRecord);
for(let userData of data){
try {
userData.userDetails = await findUserByIdForUserDetails(userData.user_id);
} catch(e) {
// Some error happened, so no user details.
// you can set here null or nothing to userDetails.
}
}
let count;
try {
count = await getAttendanceCount(searchFilters);
} catch(e){
// Same as before.
}
const callBackData = { code:200, status:'success', message:'OK', total:count, data:result };
// And here you can do whatever you want with callback data. Send to client etc.
} catch(e) {
}
NB: I've not tested this code, it will be easier for yu to play with your actual data and use Promises and async/await
Just remember that each request to db is asynchronous, and you need to make your code wait for this data.

Nodejs not working with expand in OrientDB

var database = require('./../../models/index').database
var GError = require('./../../helper/Gerror').G_Error
var libMessage = require('./../../helper/constant')
module.exports = function (input) {
return database.select('expand(first(in("haslogin")))')
.from('Login').where({
token: input.token,
active: true
}).one()
.then(function (user) {
console.log(user)
if (!user) {
throw GError(libMessage.error.INVALID_TOKEN)
}
if (user.role !== 'admin') {
throw GError(libMessage.error.INVALID_PERMISSION)
}
return database.select().from('Product').where(
'#rid = ' + input.productId
).one()
}).then(function (product) {
if (!product) {
throw GError(libMessage.error.MISSING_PRODUCT)
}
return database.update('Product').set({
status: false
}).where('#rid = ' + input.productId)
.scalar()
}).then(function (data) {
if (!data) {
throw GError(libMessage.error.HANDLE_FAIL)
}
return {
message: libMessage.success.SUCCESSFUL.message
}
}).then(function (success) {
input.returnSuccessResponse(input.res, success)
}, function (error) {
input.returnErrorResponse(input.res, error)
})
}
I'm using nodejs and Seneca. I use the OrientDB Database. I use it to expand in OrientDB but the results are not as expected.
When I console.log (user), it produced a result: {'#rid': {[String: '# 12: 37'] cluster: 12, position: 37}}
I used the query is: select expand (first (print ("haslogin"))) from where the Login token = 'f3a93042ee17776443458b315416bfd430cb7e7ab5f85e9f39232d1093ef7c74' and active = true
Results in code and in the database is not the same

Check if some query is undefined and define a callback in that case

I'm trying to do something like this:
var query = 'select max(count) from ' + series +
' where value = \'' + search + '\'';
if (db.query(query, callback) !== undefined) {
return callback;
} else {
return callback = [{
name: series,
columns: ['time', 'max'],
points: [
[0, 0]
]
}];
}
I'm trying to verify if that query is undefined or the element searched doesn't exist in the influxdb, and then arm a callback just like if the element exist, the if sentence works, but the else return an empty array
The db parameter is where are the data base configurations.
EDIT:
Thanks Osukaa for your answe. I try what you sugest but don't have response. Here is the complete function with your changes:
var counter = function (config, callback) {
var count = 'select max(count) from ' + series + ' where value = \'' + search + '\'';
db.query(count, function (err, res) {
if(err) return err;
if(res.length == 0){
return [{
name: series,
columns: ['time', 'max'],
points: [
[0, 0]
]
}];
}else{
return res;
}
});
};
The console.log shows an empty array.
EDIT 2:
Thanks #Osukaa, unfortunately that don't work, this is the error that returns:
Debug: handler, error
{"msec":395.7593630000483,"error":"Couldn't find series: items.type.updated"}
Debug: internal, error
Error: Couldn't find series: items.type.updated
EDIT 3:
I've solved the problem when try to create a series. When the series don't exist, show this error 'Error Couldn't find series [series name]', so I put this code in the error code:
db.query(qCount, function(err, res) {
if (err) {
if (err == 'Error: Couldn\'t find series: ' + name.series) {
res = newSeries;
return callback(null, res);
} else {
return callback(err);
}
} else {
if (res.length !== 0) {
return callback(null, res);
} else {
res = newSeries;
return callback(null, res);
}
}
});
When the error is equal to 'Error: Couldn\'t find series: ' + name.series, I pass the values to create them.
Thanks.
Asynchronous code doesn't work like that. When the db.query is completed it will automatically execute the callback code. It isn't necessary for you to do a return callback. Instead you could try something like this:
db.query('select max(count) from ' + series +
' where value = \'' + search + '\'' + ';', function (err, res) {
if(err) return err;
if(res.length == 0){
return [{
name: series,
columns: ['time', 'max'],
points: [
[0, 0]
]
}];
}else{
return res;
}
});
EDIT
First you make the GET to obtain the count
request.get('/itemCount')
.query({value: value.type})
.end(function(err, res) {
if (err) {
reply(err);
} else {
countElemnts(res.body[0].count);
}
});
So the server goes to the route and executes the handler:
server.route({
method: 'GET',
path: '/itemCount',
handler: function(request, reply) {
events.selectCount({
series: 'value.type',
search: request.url.query.value
}, function onSuccess(err, data) {
if (err) {
reply(err);
} else {
var result = {};
if (data.length !== 0) {
result = data[0].points.map(function(element) {
return {
count: element[1] + 1
};
});
reply(null, result);
} else {
reply(null, data);
}
}
});
}
});
Which itself calls the selectCount function to obtain the number (I updated the callback to return (null,res))
var selectCount = function(config, callback) {
var qCount = 'select max(count) from ' + config.series +
' where itemType = \'' + config.search + '\'';
db.query(qCount, function(err, res) {
if (err) {
return callback(err);
}else{
if (res !== undefined) {
return callback(null,res[0]);
}else{
var res = [{
name: config.series,
columns: ['time', 'count'],
points: [
[0, 0]
]
}];
return callback(null,res);
}
}
});
};
And when the callbacks finish, it should execute countElements:
var countElemnts = function(count) {
superagent
.post(config.eventsApiUrl)
.type('json')
.send({
name: 'items.type.updated',
data: {
id: request.params.id,
itemType: item.itemType,
count: count
}
})
.end(function() {
reply({
message: 'Item actualizado'
});
});
};

Need help to write mysql update query in node.js with callback

I am a beginner for Node.js. Please help to fix this.
Without giving WHERE clause update is working fine. Below is the script without "WHERE" clause:
var post = {name: 'Amit', mobile:'123456'};
var query = connection.query('UPDATE contacts SET ? ', post , function(err, result) {});
console.log(query.sql);
Output:
Now I added 'WHERE' clause..getting error:
var post = {name: 'Amit', mobile:'123456'};
var condition = {id:4};
var query = connection.query('UPDATE contacts SET ? ',post,' WHERE '+ condition , function(err, result) {});
console.log(query.sql);
Output:
According to the api, your should write you query like this:
connection.query('UPDATE contacts SET Name = ?,Mobile=? WHERE yourCondition = ?', [post.name,post.mobile,condition], function(err, result) {})
Try that code:
var post = {name: 'Amit', mobile:'123456'};
var condition = {id:4};
var query = connection.query('UPDATE contacts SET ? WHERE ?', [post, condition] , function(err, result) {});
console.log(query.sql);
try this ,it workd for me
connection.query('UPDATE nodeDB.USER SET USER_PASSWORD :Pass WHERE USER_NAME :Name',
{Name: 'max',Pass: '123'}, function(err, rows) {
});
Check My code also work for you.
router.all('/setLoginDetails', function (req, res) {
if(req.method == 'POST')
{
var Req = req.body;
}
else
{
var Req = req.query;
}
if(Req.lang == undefined || Req.lang == 'en')
{
const message = require('../lang/messages_en.json');
}
if(Req.id == undefined || Req.id == '')
{
return res.json({"success" : false, "Message" : message.REQUIRED , "data" : {} });
}
qb.select('id')
.where({id: Req.id})
.get('table', (err,rows) => {
if (err || rows.length == 0)
{
return res.json({"success" : false, "Message" : "No data found", "data" : Response});
}
else
{
_.each(rows, function(record) {
var token = tokenGenerate();
qb.update('token', {token: token}, {driver_id:record.id}, (err, result) => {
if (err) return console.error(err);
});
qb.select('*').where({driver_id: record.id}).get(model.DriverLogin, (err,rows) => {
var lat = Req.lat;
var lng = Req.lng;
if(Req.lat == '')
{
lat = 0.0;
}
if(Req.lng == '')
{
lng = 0.0;
}
var updateData = {lat : lat ,lng : lng, status : 'free', screen : Req.device_info, driver_id : record.id};
if(rows.length > 0)
{
qb.update('localtion', updateData, {driver_id:record.id}, (err, result) => {
if (err) return console.error(err);
});
}
else
{
qb.insert(model.DriverLogin, updateData, (err, res) => {
if (err) return console.error(err);
});
}
});
});
return res.json({"success" : true, "Message" : "Data Updated", "data" : Response});
}
}
);
});

Resources