Saving JSON from API into Mongo using Mongoose - json

I am working on a node.js app with Mongo (using the mongoose solution) to create a custom reporting solution with data from the Quickbooks Online API.
Here is the workflow:
I authenticate my app with the QBO API
I make the API call, and get JSON
This is where I would like to parse the JSON to save it to my DB.
The JSON response
{ Header:
{ Time: '2014-09-09T10:55:01-07:00',
ReportName: 'VendorBalanceDetail',
StartPeriod: '2014-10-01',
EndPeriod: '2014-10-09',
Currency: 'USD',
Option: [ { Name: 'report_date', Value: '2014-10-09' } ] },
Columns:
{ Column:
[ { ColTitle: 'Date', ColType: 'tx_date' },
{ ColTitle: 'Transaction Type', ColType: 'txn_type' },
{ ColTitle: 'Num', ColType: 'doc_num' },
{ ColTitle: 'Due Date', ColType: 'due_date' },
{ ColTitle: 'Amount', ColType: 'subt_neg_amount' },
{ ColTitle: 'Open Balance', ColType: 'subt_neg_open_bal' },
{ ColTitle: 'Balance', ColType: 'rbal_neg_open_bal' } ] },
Rows:
{ Row:
[ { Header:
{ ColData:
[ { value: 'GS & CO' },
{ value: '' },
{ value: '' },
{ value: '' },
{ value: '' },
{ value: '' },
{ value: '' } ] },
Rows:
{ Row:
[ { ColData:
[ { value: '01/31/2014' },
{ value: 'Bill' },
{ value: 'FY/2013-01/2014' },
{ value: '01/31/2014' },
{ value: '9963.14' },
{ value: '9963.14' },
{ value: '9963.14' } ],
type: 'Data' },
{ ColData:
[ { value: '02/28/2014' },
{ value: 'Bill' },
{ value: '02/2014' },
{ value: '02/28/2014' },
{ value: '6378.14' },
{ value: '6378.14' },
{ value: '16341.28' } ],
type: 'Data' },
{ ColData:
[ { value: '03/31/2014' },
{ value: 'Bill' },
{ value: '03/2014' },
{ value: '03/31/2014' },
{ value: '2556.0' },
{ value: '2556.0' },
{ value: '18897.28' } ],
type: 'Data' },
{ ColData:
[ { value: '04/30/2014' },
{ value: 'Bill' },
{ value: '04/2014' },
{ value: '04/30/2014' },
{ value: '5221.0' },
{ value: '5221.0' },
{ value: '24118.28' } ],
type: 'Data' },
{ ColData:
[ { value: '05/31/2014' },
{ value: 'Bill' },
{ value: '05/2014' },
{ value: '05/31/2014' },
{ value: '2735.96' },
{ value: '2735.96' },
{ value: '26854.24' } ],
type: 'Data' },
{ ColData:
[ { value: '06/30/2014' },
{ value: 'Bill' },
{ value: '06/2014' },
{ value: '06/30/2014' },
{ value: '658.0' },
{ value: '658.0' },
{ value: '27512.24' } ],
type: 'Data' },
{ ColData:
[ { value: '07/31/2014' },
{ value: 'Bill' },
{ value: '6-17 to 7-31' },
{ value: '07/31/2014' },
{ value: '162.32' },
{ value: '162.32' },
{ value: '27674.56' } ],
type: 'Data' } ] },
Summary:
{ ColData:
[ { value: 'Total for GS & CO' },
{ value: '' },
{ value: '' },
{ value: '' },
{ value: '27674.56' },
{ value: '27674.56' },
{ value: '' } ] },
type: 'Section' }
My model:
module.exports = mongoose.model('vbDetail', {
company_name: String,
row:{
date: Date,
transaction_type: String,
transaction_num: String,
due_date: Date,
amount: Number,
open_balance: Number,
balance: Number,
identifier: String,
processing_date: Date,
processing_amount :Date,
notes: String
}
})
The last three fields are custom fields that I want to store in addition to the JSON response.
My question is how to I take the JSON from the response and parse it so it "adheres" to my model?

Related

Json Schema allowing additional properties even though additionalProperties is set to false

Given the following schema:
export const MESSAGE_SCHEMA = {
additionalProperties: false,
type: 'object',
properties: {
comment: { type: 'string' },
startAt: { type: 'string' },
states: {
type: 'object',
minProperties: 1,
patternProperties: {
"^[A-Za-z]+[A-Za-z0-9 ]{0,127}$": {
type: 'object',
properties: {
type: { type: 'string', enum: TASK_TYPES_ALL_ENUM },
next: { type: 'string' },
end: { type: 'boolean' },
choices: {
type: 'array',
items: {
type: 'object'
},
minItems: 2
},
default: { type: 'string' },
error: { type: 'string' },
cause: { type: 'string' },
resource: { type: 'string' },
},
required: ['type'],
allOf: [
// Make choices required if task type = 'choice'
{
if: {
properties: { type: { const: TASK_TYPE_CHOICE } }
},
then: {
required: ['type', 'choices']
}
}
]
}
},
additionalProperties: false
}
},
required: ['startAt','states']
};
If I send a payload into my API with a key within the "states" object that doesn't match the pattern, it always allows the request... The behavior as I understood should prevent this with the properties / patternProperties + additionalProperties = false, but this is not the case...
For example - this should error since the pattern does not match and no additional properties are allowed, but I get a response from the API as though it was validated successfully:
{
"eventNamespace": "state",
"eventType": "transition",
"payload": {
"foo": "bar"
},
"message": {
"startAt": "foo",
"states": {
"!##^#^": {
"type": "choice",
"choices": []
}
}
}
}
If I then put a value that matches the pattern, I get a validation failure (as expected):
{
"eventNamespace": "state",
"eventType": "transition",
"payload": {
"foo": "bar"
},
"message": {
"startAt": "foo",
"states": {
"valid property example": {
"type": "choice",
"choices": []
}
}
}
}
Response:
{
"statusCode": 400,
"error": "Bad Request",
"message": "body/message/states/valid property example/choices must NOT have fewer than 2 items"
}
Your schema is fine. When I run it through my validator I get:
{
"errors" : [
{
"error" : "additional property not permitted",
"instanceLocation" : "/states/!##^#^",
"keywordLocation" : "/properties/states/additionalProperties"
},
{
"error" : "not all additional properties are valid",
"instanceLocation" : "/states",
"keywordLocation" : "/properties/states/additionalProperties"
},
{
"error" : "not all properties are valid",
"instanceLocation" : "",
"keywordLocation" : "/properties"
}
],
"valid" : false
}
I suggest you open a bug report for the implementation you are using.
Most likely, this is because Fastify validator removes additional properties by default.
You can disable this behaviour by setting removeAdditional: false:
const server = Fastify({
ajv: {
customOptions: {
removeAdditional: false
}
}
})
For more information https://www.fastify.io/docs/latest/Reference/Validation-and-Serialization/

how to display json in table vuejs

how to display the following json data ?
i have json data like this, and want to display it in table, i use vue-bostrapt .
Previously I tried like this, but it's not perfect.
this my json
[
{
"id":"1",
"name": "KINTIL",
"desc": "Kintil is good",
"location": [
{
"prov": "Jawa Barat",
"city": "Bandung"
},
{
"prov": "Banten",
"city": "Tanggerang"
}
],
"applied": [
{
"item_name": "galian"
},
{
"item_name": "timbunan"
}
],
"exception": [
{
"ex_name": "F001",
"ex_value": "001001"
},
{
"ex_name": "M001",
"ex_value": "002002"
}
]
}
]
and this html
<b-table class="table spacing-table" style="font-size: 13px;" show-empty
:items="inovasi" :fields="fields" :current-page="currentPage" :per-page="0" :filter="filter" >
</b-table>
and this my script
import json from "../static/data.json";
export default {
name: 'tes',
data() {
return {
inovasi:[],
filter: null,
fields: [
{
key: 'id',
label: 'id',
sortable: true
},
{
key: 'name',
label: 'name',
sortable: true
},
{
key: 'location',
label: 'location',
sortable: true
},
{
key: 'applied',
label: 'applied',
sortable: true
},
{ key: 'actions', label: 'Doc' }
],
currentPage: 0,
perPage: 5,
totalItems: 0
}
},
mounted() {
this.inovasi = json;
},
computed:{
},
methods: {
}
}
this result
how to display location and applied , into a single row table ?
thanks in advance for those who have answered :)
thanks
You can do it using formatter like
fields: [
{
key: 'id',
label: 'id',
sortable: true
},
{
key: 'name',
label: 'name',
sortable: true
},
{
key: 'location',
label: 'location',
sortable: true,
formatter: (value, key, item) => {
return value.map(x => 'prov: ' + x.prov + ' city:' + x.city).join(", ")
}
},
{
key: 'applied',
label: 'applied',
sortable: true,
formatter: (value, key, item) => {
return value.map(x => x.item_name).join(", ")
}
},
{ key: 'actions', label: 'Doc' }
],
It will show for the location column this: prov: Jawa Barat city:Bandung, prov: Banten city:Tanggerang and for the applied column this: galian, timbunan

Map mongo aggregation result to array

I have a mongo query that looks like this:
db.myCollection.aggregate([ {
$group: {
_id: null,
price: {
$sum: "$price"
},
inventory: {
$sum: "$inventory"
}
}
}])
Which returns
{
"_id" : null,
"price" : 26,
"inventory" : 5,
}
I would like a query which would rather return something like this:
[
{
name: "price",
amount: 26
},
{
name: "inventory",
amount: 5
}
]
EDIT:
How would I write this in Java with Spring Data? I can group and sum but don't know how to project it?
Aggregation aggregation = newAggregation(
group("$id")
.sum("price").as("price")
.sum("inventory").as("inventory")
);
You'll need to use $project. It allows us to define which fields will be returned, as well as their format.
db.myCollection.aggregate([{
$group: {
_id: null,
price: {
$sum: "$price"
},
inventory: {
$sum: "$inventory"
}
}
},
{
$project: {
_id: 0 //removes _id from result
something: [
{name: "price", amount: "$price"},
{name: "inventory", amount: "$inventory"}
]
}
}])
That will give you:
{
"something" : [
{
"name" : "price",
"amount" : 26
},
{
"name" : "inventory",
"amount" : 5
}
]
}
You can use below aggregation
db.collection.aggregate([
{ "$project": {
"data": {
"$map": {
"input": { "$objectToArray": "$$ROOT" },
"in": { "name": "$$this.k", "amount": "$$this.v" }
}
}
}},
{ "$unwind": "$data" },
{ "$replaceRoot": { "newRoot": "$data" }},
{ "$match": { "amount": { "$ne": null }}
}
])

Kendo grid with default Columns

I want to show to users subset of columns and allow them to add extra columns if needed. I am struggling to load only subset of columns on load. Please find the code below I have done.
<kendo-grid k-options="vm.mainGridOptions"
k-columns="vm.mainGridColumns"
k-sortable="true"
k-filterable="{mode: 'row'}"
k-column-menu="true"
k-serverFiltering="false"
k-pageSize="10"
k-pageable="{ pageSizes: [5, 10, 25, 50, 100] }"> </kendo-grid>
Controller code
var mainGridDataSource = new kendo.data.DataSource({
transport: { read: mainGridReadEventHandler, cache: true },
serverFiltering: false,
page: 1,
pageSize: 10,
schema: {
data: 'data',
total: 'total',
model: {
fields: {
customerName: { type: "string" },
serviceAccountStatus: { type: "string" },
customerNumber: { type: "string" },
serviceType: { type: "string" },
utilityAccountNumber: { type: "string" },
serviceAddress: { type: "string" },
billingAccountNumber: { type: "string" },
utility: { type: "string" },
phoneNumber: { type: "string" },
email: { type: "string" }
}
}
}
});
vm.mainGridColumns = [
{
field: "customerName",
title: "Name",
template:
"<a ui-sref='resiservice.account-search.customer-details({ customerId:${customerId}, serviceAccountId:${serviceAccountId} })'>${customerName}</a>"
},
{
field: "serviceAccountStatus",
title: "Status"
},
{
field: "customerNumber",
title: "NAP Customer #"
},
{
field: "serviceType",
title: "Commodity"
},
{
field: "utilityAccountNumber",
title: "Utility/Account #"
},
{
field: "serviceAddress",
title: "Service Address"
},
{
field: "billingAccountNumber",
title: "NAP Account #"
},
{
field: "utility",
title: "Utility"
},
{
field: "phoneNumber",
title: "Phone #"
},
{
field: "email",
title: "Email Address"
}
];
Currently columns list coming like this first time
And i want to achive like this
Use columns.hidden property to hide a column, i.e.
{
field: "utility",
title: "Utility",
hidden: true
},
{
field: "phoneNumber",
title: "Phone #",
hidden: true
},
{
field: "email",
title: "Email Address",
hidden: true
}
For example:
http://dojo.telerik.com/EzuFO
The column is still visible on the list of columns in menu.

Using json data how to create form in sencha

I want to read json data from file - content of the json file shown below
{
"form": {
"fields" : [
{
"field":"textfield",
"name": "username",
"constrain": "5-10",
"value": ""
},
{
"field":"textfield",
"name": "password",
"constrain": "5-10",
"value": ""
},
{
"field":"datepickerfield",
"name": "Birthday",
"constrain": "5-10",
"value": "new Date()"
},
{
"field":"selectfield",
"name": "Select one",
"options":[
{"text": "First Option", "value": 'first'},
{"text": "Second Option", "value": 'second'},
{"text": "Third Option", "value": 'third'}
]
},
]
}
}
Model
Ext.define('dynamicForm.model.Form', {
extend: 'Ext.data.Model',
config: {
fields: [
{name: 'field', type: 'string'},
{name: 'name', type: 'string'},
{name: 'constrain', type: 'string'},
{name: 'value', type: 'string'}
],
hasMany: {model: 'dynamicForm.model.SelectOption', name: 'options'}
}
});
Ext.define('dynamicForm.model.SelectOption', {
extend: 'Ext.data.Model',
config: {
fields: [
{name: 'text', type: 'string'},
{name: 'value', type: 'string'}
]
}
});
store
Ext.define('dynamicForm.store.FormStore', {
extend : 'Ext.data.Store',
storeId: 'formStore',
config : {
model : 'dynamicForm.model.Form',
proxy : {
type : 'ajax',
url : 'form.json',
reader : {
type : 'json',
rootProperty : 'form.fields'
}
},
autoLoad: true
}
});
This what i tried so for.
var fromval = Ext.create('dynamicForm.store.FormStore');
fromval.load(function (){
console.log(fromval);
// i added register view which having form panel with id "testForm"
Ext.Viewport.add({
xtype : 'register'
});
for(i=0; i< fromval.getCount(); i++) {
console.log("------");
Ext.getCmp('testForm').add({
xtype: fromval.getAt(i).data.field,
label: fromval.getAt(i).data.name,
value: fromval.getAt(i).data.value,
options: [
{text: "First Option", value: "first"},
{text: "Second Option", value: "second"},
{text: "Third Option", value: "third"}
]
});
}
});
two text fileds and date are woking good, but i don't know how to get options for select field from store, just heard coded now.
over all Based on the above json data, i need to create sencha form dynamically.
Better to follow MVC structure:
Create a model:
Ext.define('MyApp.model.FormModel', {
extend: 'Ext.data.Model',
config: {
fields: ["field","name"]
}
});
A store with proxy:
Ext.define('MyApp.store.FormStore',{
extend: 'Ext.data.Store',
config:
{
model: 'MyApp.model.FormModel',
autoLoad:true,
proxy:
{
type: 'ajax',
url : 'FormData.json', //Your file containing json data
reader:
{
rootProperty:'form.fields'
}
}
}
});
The formData.json file:
{
"form": {
"fields" : [
{
"field":"textfield",
"name": "username"
},
{
"field":"textfield",
"name": "password"
},
]
}
}
And then use the FormStore to fill the form data as you need.
Ext.define('MyApp.view.LoginPage', {
extend: 'Ext.form.Panel',
config: {
items:{
xtype:'fieldset',
layout:'vbox',
items:[{
flex:1,
xtype:'textfield',
id:'namefield',
placeHolder:'Username'
},{
flex:1,
xtype:'passwordfield',
id:'passwordfield',
placeHolder:'Password'
}]
},
listeners:{
painted:function()
{
var store=Ext.getStore('FormStore');
while(!store.isLoaded())
{
console.log("loading...");
}
var record=store.getAt(0);
Ext.getCmp('namefield').setValue(record.data.name);
Ext.getCmp('passwordfield').setValue(record.data.password);
}
}
}
});
{
"data":[
{
"xtype":"textfield",
"title":"UserName",
"name": "username"
},
{
"xtype":"textfield",
"title":"password",
"name": "password"
},
{
"xtype":"textfield",
"title":"phone no",
"name": "birthday"
},
{
"xtype":"textarea",
"title":"address",
"name": "address"
}
]
}
Ext.define('dynamicForm.model.FormModel', {
extend: 'Ext.data.Model',
fields: ['field', 'name']
});
Ext.define('dynamicForm.store.FormStore', {
extend : 'Ext.data.Store',
model : 'dynamicForm.model.FormModel',
proxy :
{
type : 'ajax',
url : 'data/user.json',
reader :
{
type : 'json',
rootProperty:'data'
},
autoLoad: true
}
});
Ext.define('dynamicForm.view.DynaForm',{
extend:'Ext.form.Panel',
alias:'widget.df1',
items:[]
});
Ext.application({
name:'dynamicForm',
appFolder:'app',
controllers:['Users'],
launch:function(){
Ext.create('Ext.container.Viewport',{
items:[
{
xtype:'df1',
items:[]
}
]
});
}
});
Ext.define('dynamicForm.controller.Users',{
extend:'Ext.app.Controller',
views:['DynaForm'],
models:['FormModel'],
stores:['FormStore'],
refs:[
{
ref:'form1',
selector:'df1'
}
],
init:function(){
console.log('in init');
this.control({
'viewport > panel': {
render: this.onPanelRendered
}
});
},
onPanelRendered: function() {
var fromval=this.getFormStoreStore();
var form=this.getForm1();
fromval.load({
scope: this,
callback: function(records ,operation, success) {
Ext.each(records, function(rec) {
var json= Ext.encode(rec.raw);
var response=Ext.JSON.decode(json);
for (var i = 0; i < response.data.length; i++) {
form.add({
xtype: response.data[i].xtype,
fieldLabel: response.data[i].title,
name: response.data[i].name
});
}
//form.add(Ext.JSON.decode(json).data);
form.doLayout();
});
}
});
}
});
It will be done automatically if you insert it into any extjs component content :
var jsonValues = "{
"form": {
"fields" : [
{
"field":"textfield",
"name": "username"
},
{
"field":"textfield",
"name": "password"
},
]
}
}";
var panel = new Ext.Panel({
id : 'myPanel',
items : [jsonValues]
});
panel.show();