Sails GET request doesn't return data from all columns in my Postgres DB - postgresql

I'm using $sailsSocket to make my GET and POST requests. My POST request looks like this;
$sailsSocket.post('/schedules/toDateObj',
{ jobSchedObj:
{ repair_shop_equipment_id: response.config.data.schedEquip.rsrcId,
repair_history_id: response.data.id,
technician_id: response.data.technician_id,
allotted_time: response.data.allotted_time,
times: timeObj,
repair_shop_id: $localstorage.get('shopId')
}
})
.success(function(){
$location.path('/app/checkin');
})
.error(function (response){
console.log(response);
});
And here is the table it saves to...
Everything saves fine I even threw a console.log in my ScheduleController to check what was being inserted in the database with my POST request. Here is the output;
The problem is when I make a GET request to the Schedule table it comes back with everything except repair_shop_equipment_id. Here is the get request;
var firstDay = scope.getJobsFor[0];
var lowerBound = firstDay.open_time;
var lastDay = scope.getJobsFor[scope.getJobsFor.length - 1];
var upperBound = lastDay.close_time;
$sailsSocket.get("/schedules", {params:
{where: {
repair_shop_id: scope.shopId,
technician_id: scope.schedTech.id,
repair_shop_equipment_id: scope.schedEquip.rsrcId,
scheduled_start_time:{ date: {'>':lowerBound, '<':upperBound}}
}
}
})
.success(function (response){
And this is the response...
Here is a link to a Gist with my associated Sails models and the schedule controller;
Is there something wrong with one of my model configurations? Thanks.

Related

SharePoint CAML + REST + Paging issue

I suppose I have found another SP bug... but maybe I do something wrong.
I have this POST request:
https://dmsdev/coll/f7c592adcb4c4e5996c2de00d444a94c/_api/Web/Lists/GetByTitle('1')/GetItems?$expand=ContentType&$select=Id,SonarDocId,ContentTypeId,EncodedAbsURL,Modified,ContentType/Name
With body:
{"query":{"ViewXml":"<View><Query><OrderBy><FieldRef Name='Modified'/></OrderBy></Query><RowLimit>50</RowLimit></View>","ListItemCollectionPosition":{"PagingInfo":"Paged=TRUE&p_Modified=2017-08-10T07:25:28"}}}
As you can see I do a CAML query with ORDER BY Modified column and I want to take items starting from the item after the item with some modified date but looks like this is not working... I mean similar request on other SP environment works, and on the other env it is not working... it takes all items starting from the first one after ordering by modified... I have no idea what is wrong :/
You could check my sample test script.
<script type="text/javascript">
function restCallwithCaml(listName, caml,PID) {
/// get the site url
var siteUrl = _spPageContextInfo.siteAbsoluteUrl;
/// set request data
var data = {
"query": {
"__metadata":
{ "type": "SP.CamlQuery" },
"ViewXml": caml,
"ListItemCollectionPosition": {
"PagingInfo": "Paged=TRUE&p_ID=" + PID
}
}
};
/// make an ajax call
return $.ajax({
url: siteUrl + "/_api/web/lists/GetByTitle('" + listName + "')/GetItems",
method: "POST",
data: JSON.stringify(data),
headers: {
"X-RequestDigest": $("#__REQUESTDIGEST").val(),
'content-type': 'application/json;odata=verbose',
'accept': 'application/json;odata=verbose'
}
});
}
function GetItemsPaging() {
var pageLimit = 2;
var pageNumber = 0;
var caml = "<View><Query><Where><Geq><FieldRef Name='ID'/><Value Type='Number'>1</Value></Geq></Where></Query><RowLimit>" + pageLimit + "</RowLimit></View>";
var listName = "ChildB";
restCallwithCaml(listName, caml, pageNumber).done(function (data) {
if (data.d.results.length == pageLimit) {
pageNumber++;
//add to array or display
var PID=data.d.results[data.d.results.length - 1].Id;
alert(PID);
restCallwithCaml(listName, caml, PID).done(function (data) {
//add to array or display
alert(data.d.results[data.d.results.length - 1].Id);
})
}
});
}
</script>
Original thread
The problem was with my understanding of how this whole thing works + time zones
I had to write a paging query eg:
Paged=TRUE&p_ID=10&p_Modified=2018-12-14T18:52:00
So I had to add p_Modified parameter from the last item from the previous page... Additionally this data has to be in UTC, so for example I can execute get query with the time returned by the CAML
https://server/site/_api/web/RegionalSettings/TimeZone/localTimeToUTC(#date)?#date='2018-12-14T11:52:00'
And date returned by this call should be passed in p_Modified.

Handling an OPTIONS request in a Keystone.js API

I'm building an SPA with Aurelia backed by Keystone.
When POSTing from my Aurelia view, the Content-Type is set to application/json, which of course, incurs an OPTIONS request when coming from the client-side.
My Keystone init settings are wide open on cors for local development:
keystone.init({
...
'cors allow origin': true,
'cors allow methods': true,
'cors allow headers': true,
...
});
My Keystone route bindings for the API are:
exports = module.exports = function(app) {
app.all('/api/*', keystone.middleware.cors);
app.post('/api/inquiry', keystone.middleware.api, routes.api.inquiries.post);
};
My Keystone API view is:
var keystone = require('keystone'),
Inquiry = keystone.list('Inquiry');
exports.post = function(req, res) {
var inquiry = new Inquiry.model({
name: {
first: req.body.name.first,
last: req.body.name.last
},
email: req.body.email,
phone: req.body.phone,
question: req.body.question
});
inquiry.save(function(error) {
if (error) {
return res.apiError(error);
}
return res.apiResponse({
'inquiry': inquiry
});
});
};
The problem I'm having is that the OPTIONS request 404s instead of returning a 200.
Even if I manually handle the OPTIONS request and simply return a status of 200, the POST request doesn't follow the OPTIONS request. Am I mis-understanding the OPTIONS request lifecycle?
I've also tried passing in different content types like 'application/x-www-form-urlencoded and text/plain with data matching those formats, which don't cause the OPTIONS request, but Keystone isn't parsing the contents of those POSTs.
What am I doing wrong?
Apparently I missed the part in the Keystone documentation where you can customize the Express instance before you hand it to Keystone.
// keystone.js
var keystone = require('keystone');
var express = require('express');
var cons = require('consolidate');
var nunjucks = require('nunjucks');
var bodyParser = require('body-parser');
var app = express();
app.use(bodyParser.text());
keystone.app = app;
Then in my Aurelia app, I call JSON.stringify(myObject) before POSTing it to Keystone. Subsequently in my Keystone view, I just have to parse the string back to JSON:
exports.post = function(req, res, next) {
if (!req.body) {
return res.sendStatus(400);
}
var data = JSON.parse(req.body),
inquiry = new Inquiry.model(data);
inquiry.save(function(error) {
if (error) {
return res.apiError(error);
}
return res.apiResponse({
'inquiry': inquiry
});
});
};

Using Restangular, can I use a jsonResultsAdapterProvider when needing to override the id field?

I've got a mySql db with non-standard IDs and field names, so I was trying to use both jsonResultsAdapterProvider and setRestangularFields. Here's the code in my app.config file:
RestangularProvider.setBaseUrl(remoteServiceName);
RestangularProvider.setRestangularFields({id: 'personID'});
RestangularProvider.addResponseInterceptor(function(data, operation, what, url, response, deferred) {
if (data.error) {
return data.error;
}
var extractedData = data.result;
return jsonResultsAdapterProvider.$get().camelizeKeys(extractedData);
});
RestangularProvider.addRequestInterceptor(function(elem, operation, what, url) {
return jsonResultsAdapterProvider.$get().decamelizeKeys(elem);
});
It's all good until I try to do a put/save. When I look at the request payload within the browser dev tools, it's: {"undefined":12842} (but the url is correct, so I know the id is set) If I don't use the ResultsAdapter and change the id field to Person_ID, payload looks good, so I know I'm making the right calls to Get and Save the Restangular objects. But for what it's worth, here's the code:
$scope.tests = Restangular.all('members').getList().$object;
vm.testEdit = function () {
$scope.test = Restangular.one('members', 12842).get().then(function(test) {
var copy = Restangular.copy(test);
copy.title = 'xxxx';
copy.put(); // payload was: undefined: 12842
});
}
// I also tried customPUT...
// copy.customPUT(copy, '', {}, {'Content-Type':'application/x-www-form-urlencoded'});
I tried "fixing" the id other ways too, too. like this:
Restangular.extendModel('members', function(model) {
model.id = model.personID;
return model;
});
but that messed up the urls, causing missing ids. And I tried getIdFromElem, but it only got called for my objects created with Restangular.one(), not with Restangular.all()
Restangular.configuration.getIdFromElem = function(elem) {
console.log('custom getIdFromElem called');
if (elem.route === 'members') { // this was never true
return elem[personID];
}
};
It seems like Restangular needs to substitute 'personID' most of the time, but maybe it needs 'Person_ID' at some point during the Save? Any ideas on what I could try to get the Save working?
I finally figured it out! The problem was in my config code and in the way I was decamelizing. Because of inconsistencies in my db field names (most use underscores, but some are already camelCase), I was storing the server's original elem names in an array within the jsonResultsAdapterProvider. But since I was calling jsonResultsAdapterProvider.$get().camelizeKeys(extractedData); within the interceptors, I was reinstantiating the array each time I made a new request. So, the undefined in the PUT request was coming from my decamelizeKeys() method.
My updated config code fixed the problem:
RestangularProvider.setBaseUrl(remoteServiceName);
RestangularProvider.setRestangularFields({id: 'personID'});
var jsonAdapter = jsonResultsAdapterProvider.$get();
RestangularProvider.addResponseInterceptor(function(data, operation, what, url, response, deferred) {
if (data.error) {
return data.error;
}
var extractedData = data.result;
// return extractedData;
return jsonAdapter.camelizeKeys(extractedData);
});
RestangularProvider.addRequestInterceptor(function(elem, operation, what, url) {
return jsonAdapter.decamelizeKeys(elem);
});

Getting a response from an Azure insert

I have inherited the development of an iOS app that connects to an Azure mobile service, and I'm stuck on getting an acceptable response from my insert operations. Specifically I want to get back the object that was inserted, or at least the value of its id field, from a Custom API script that the previous developer on this project created.
A truncated version of the Custom API script I'm using looks like:
exports.post = function(request, response) {
var mssql = request.service.mssql;
var sql = "INSERT INTO Reservation (<field names>)" +
" VALUES (<field values>); "
+"SELECT id FROM Reservation WHERE __updatedAt = (SELECT MAX(__updatedAt) FROM Reservation);";
mssql.query(sql, {
success: function(results) {
console.log("after post - results = " + results);
response.send(statusCodes.OK, results);
}
});
};
When I run the iOS app and post a Reservation (using the AFNetworking class to communicate with the server), I get back a response object with an empty array. Furthermore, inspecting the Azure log for the results of the console.log statement in my function, I see two results: "after post - results = [object Object]" and "after post - results =".
I'm clearly doing something wrong, but I don't understand what. I have tried a number of other different approaches, all with similarly unsatisfactory results. For what it's worth, the "get" script for this class works just fine. I wonder if anybody can help me get this "post" script right.
As you noted in your logs, the success callback for the mssql.query call is being called twice - since you have two statements in your query. When you first call response.send, that's the response which is sent back to the client. The first callback will contain the results for the INSERT call, which is not what you want to return. You should use a flag to indicate which result you're receiving, and only return if it's the one you want:
exports.post = function(request, response) {
var mssql = request.service.mssql;
var sql = "INSERT INTO Reservation (<field names>)" +
" VALUES (<field values>); "
+"SELECT id FROM Reservation WHERE __updatedAt = (SELECT MAX(__updatedAt) FROM Reservation);";
var firstCall = true;
mssql.query(sql, {
success: function(results) {
console.log("after post - results = " + results);
if (firstCall) {
firstCall = false;
} else {
response.send(statusCodes.OK, results);
}
}
});
};

Sending POST requests to a nested API endpoint URL using Ember Data

I see several questions on SO attempting to solve this problem of sending POST requests to nested API resource routes.
See:
- [Sending REST requests to a nested API endpoint URL using Ember Data(Sending REST requests to a nested API endpoint URL using Ember Data)
- Custom request URLs in Ember model
I've started overloading the createRecord, updateRecord, and deleteRecord methods on the RESTAdapter to attempt some sort of hackery solution to building the correct URL. Now, using a method similar to this is the route I've taken so far.
Here is the updateRecord method in their solution:
App.UserAdapter = DS.RESTAdapter.extend({
updateRecord: function(store, type, record) {
if(!record.get('parent') || null === record.get('parent')){
return this._super(store, type, record);
}
var data = {};
var serializer = store.serializerFor(type.typeKey);
var parent_type = record.get('parent');
var parent_id = record.get(parent_type).get('id');
var child_parts = Ember.String.decamelize(type.typeKey).split('_');
var path = Ember.String.pluralize(parent_type) + '/' + parent_id + '/' + Ember.String.pluralize(child_parts.pop());
serializer.serializeIntoHash(data, type, record);
var id = record.get('id');
return this.ajax(this.buildURL(path, id), "PUT", { data: data });
}
....
});
This method should work great in tandem with adding the parent type to the model and ensuring the related parent model id is also represented on the model. For PUT and DELETE requests, this shouldn't be a problem, as we already have the parent ID relation on the object in store.
Project model:
App.ProjectModel = DS.Model.extend({
name: DS.attr('string'),
createdAt: DS.attr('date'),
updatedAt: DS.attr('date'),
workspace : DS.belongsTo('workspace'),
parent: 'workspace',
....
});
Where this method appears to go awry for me is in creating new resources with a post. I've attempted it, but since the payload hasn't been returned from the API server with the related parent ID, I actually don't have access to it.
Here's my crappy first attempt, that doesn't work. The workspace id always returns null.
createRecord: function(store, type, record) {
if (!record.get('parent') || null === record.get('parent')){
return this._super(store, type, record);
}
var data = {};
var serializer = store.serializerFor(type.typeKey);
var parent_type = record.get('parent');
var parent_id = record.get(parent_type).get('id');
var path = Ember.String.pluralize(parent_type) + '/' + parent_id + '/' + type.typeKey);
serializer.serializeIntoHash(data, type, record, { includeId: true });
return this.ajax(this._buildURL(path, null), "POST", { data: data });
},
Got any thoughts on how I can get the parent ID, before I have a saved record?
I am the author of the solution you cited in your question.
What does your model hook look like in the route where you are creating the new ProjectModel?
Assuming your Workspace route looks something like:
App.WorkspaceRoute = Ember.Route.extend({
model: function (params) {
return this.store.find('workspace', params.id);
}
});
Then your Workspace Project add/create route's model hook would need to be something like:
App.WorkspaceProjectAddRoute = Ember.Route.extend({
model: function () {
var workspace = this.modelFor('workspace');
return this.store.createRecord('project', {
workspace: workspace
});
}
}
I hope this makes some sense...