How to define "ENUM" type and put values in a loopback model itself? - loopbackjs

How to define "ENUM" type and put values in a model itself? If thats not possible, then in the documentation, its mentioned to use enum like this
https://loopback.io/doc/en/lb3/MySQL-connector.html#enum
But where should I put this code as per best practice ?

You could add custom validation to your model, so it would check if the value you're passing is correct. You can find a more elaborated answer here:
Can I define a custom validation with options for Loopback?

You can use this way with MYSQL Connector.
"properties": {
"name": {
"type": "string",
"mysql": {
"columnName": "name",
"dataType": "ENUM('Daily', 'Week Days','Weekends','Monthly','Custom')",
"default": "Week Days"
}
}
}
`

Use ENUM property in JSON Schema
#property({
type: 'string',
required: true,
jsonSchema: {
enum: ['Daily', 'Week Days','Weekends','Monthly','Custom'],
},
})

Related

Amazon SP-API Listings API putListingsItem How To Update price and quantity? Node.js

I am using amazon-sp-api (JavaScript client for the Amazon Selling Partner API) but this is not limited to this client. All I want to do is use the Amazon SP-API Listings API's putListingsItem call to update the price and quantity of an item I have listed.
productType
According to the ListingsItemPutRequest docs, productType and attributes are required for this call.
Firstly, to obtain the correct productType value, you are supposed to search for a product definitions type using the Product Type Definitions API. So, I do that, and call searchDefinitionsProductTypes, just to discover my product has no matching product type.
Ultimately, I gave the value PRODUCT for productType field. Using PRODUCT, I made the getDefinitionsProductType call and got an object containing an array of propertyNames, shown below:
"propertyNames": [
"skip_offer",
"fulfillment_availability",
"map_policy",
"purchasable_offer",
"condition_type",
"condition_note",
"list_price",
"product_tax_code",
"merchant_release_date",
"merchant_shipping_group",
"max_order_quantity",
"gift_options",
"main_offer_image_locator",
"other_offer_image_locator_1",
"other_offer_image_locator_2",
"other_offer_image_locator_3",
"other_offer_image_locator_4",
"other_offer_image_locator_5"
]
},
On seeing this, I decide list_price and fulfillment_availability must be the price and quantity and then try using these in my code below.
attributes
The attributes value is also required. However, their current docs show no clear example of what to put for these values, which are where I must put price and quantity somewhere.
I found this link about patchListingsItem and tried to implement that below but got an error.
code:
// trying to update quantity... failed.
a.response = await a.sellingPartner.callAPI({
operation:'putListingsItem',
path:{
sellerId: process.env.SELLER_ID,
sku: `XXXXXXXXXXXX`
},
query: {
marketplaceIds: [ `ATVPDKIKX0DER` ]
},
body: {
"productType": `PRODUCT`
"requirements": "LISTING_OFFER_ONLY",
"attributes": {
"fulfillment_availability": {
"fulfillment_channel_code": "AMAZON_NA",
"quantity": 4,
"marketplace_id": "ATVPDKIKX0DER"
}
}
});
console.log( `a.response: `, a.response )
error:
{
"sku": "XXXXXXXXXXXX",
"status": "INVALID",
"submissionId": "34e1XXXXXXXXXXXXXXXXXXXX",
"issues": [
{
"code": "4000001",
"message": "The provided value for 'fulfillment_availability' is invalid.",
"severity": "ERROR",
"attributeName": "fulfillment_availability"
}
]
}
I also tried using list_price :
// list_price attempt... failed.
a.response = await a.sellingPartner.callAPI({
operation:'putListingsItem',
path:{
sellerId: process.env.SELLER_ID,
sku: `XXXXXXXXXXXX`
},
query: {
marketplaceIds: [ `ATVPDKIKX0DER` ]
},
body: {
"productType": `PRODUCT`
"requirements": "LISTING_OFFER_ONLY",
"attributes": {
"list_price": {
"Amount": 90,
"CurrencyCode": "USD"
}
});
console.log( `a.response: `, a.response )
Error (this time seems I got warmer... maybe?):
{
"sku": "XXXXXXXXXXXX",
"status": "INVALID",
"submissionId": "34e1XXXXXXXXXXXXXXXXXXXX",
"issues": [
{
"code": "4000001",
"message": "The provided value for 'list_price' is invalid.",
"severity": "ERROR",
"attributeName": "list_price"
}
]
}
How do you correctly specify the list_price or the quantity so this call will be successful?
Just tryin to update a single item's price and quantity.
The documentation for this side of things is terrible. I've managed to get some of it through a fair bit of trial and error though.
Fulfillment and Availability can be set with this block of JSON
"fulfillment_availability": [{
"fulfillment_channel_code": "DEFAULT",
"quantity": "9999",
"lead_time_to_ship_max_days": "5"
}]
and List price gets set, oddly, with this block. I'm still trying to find out how to set the List Price with Tax however.
"purchasable_offer": [{
"currency": "GBP",
"our_price": [{"schedule": [{"value_with_tax": 285.93}]}],
"marketplace_id": "A1F83G8C2ARO7P"
}]
Hope this helps you out :)

Ember Nested Data in JSON Response

I'm having some trouble accessing some nested data in one of my Ember models. Below is the JSON response...
{
"fields": {
"header": {
"name": "header",
"type": "text",
"localize": false,
"options": []
},
"body": {
"name": "body",
"type": "textarea",
"localize": false,
"options": []
}
},
"entries": [
{
"header": "header test",
"body": "body test body test body test",
"_mby": "5a395e8430c2ddoc683600766",
"_by": "5a395e8430c2ddoc683600766",
"_modified": 1513709605,
"_created": 1513709605,
"_id": "5a3960253d578doc735798511"
}
],
"total": 1
}
Here is my current serializer
import DS from 'ember-data';
export default DS.RESTSerializer.extend({
normalizeResponse(store, primaryModelClass, payload, id, requestType)
{
payload = {
entries: payload.entries
};
return this._super(store, primaryModelClass, payload, id, requestType);
}
});
I'm trying to get the Entries in my template. Perhaps I need some help better serializing this with NormalizeResponse? I'm very stumped so please share if you have any ideas!
Thanks!!
The ember-data RESTAdapter expects the JSON to contain keys that correspond to model names and values to be arrays of JSON objects with key-value pairs according to the respective models' attribute-name--attribute-value-type definitions*.
So if you have a model named entry containing header: attr('string'), body: attr('string'), the following JSON should lead to an entry in the store:
{
"entries": [{
"header": "header test",
"body": "body test body test body test",
"id": "5a3960253d578doc735798511"
}],
}
There is a way to convince ember-data to customize the id field name (to accept _id instead of id). The build-in pluralization rules should include the entry->entries pluralization (but I cannot vouch for it).
Any top-level key that does not correspond to a model name should be ignored anyway, so no need to filter it out manually (unless you have models named field or total).
If you then return this.store.findAll('entry') (or query('entry',{/*something*/}) in your route's model hook, you should be able to look over {{#each model as |entry|}} in your controller's template.
(It is good practice to not use model as the model name, but if you want it to be entries, you have to specify that explicitly somewhere, i.e. the controller or the route's setupController method.)
*The point of repeating the name of the model as top-level key in the json response (presumably to an API endpoint of the same name) is that you can include other models if you whish and they will be added to the store as well.

In Loopback.js, how to query on embedded models?

I'm using MongoDB connector and have a Considerate and Discussion model setup like this:
model-config.json:
{
"Considerate": {"dataSource": "db"},
"Discussion": {"dataSource": "transient"}
}
considerate.json:
{
"name": "Considerate",
"base": "PersistedModel",
"relations": {
"discussion": {"type": "embedsOne", "model": "Discussion"}
}
}
discussion.json:
{
"name": "Discussion",
"base": "Model",
"properties": {
"name": {"type": "string"}
},
"relations": {
"considerate": {"type": "belongsTo", "model": "Considerate"}
}
}
}
How can I query for Considerates based on Discussion's properties? For example, something like this:
Considerate.find({where: {'discussion.name': 'snow white'}})
Inspecting Mongo persisted data, I see that in each Considerate document, there's a _discussion property. Consequently, Considerate.find({where: {'_discussion.name': 'snow white'}}) works. However, this is undocumented and wondering if there is a documented/reliable way to to this.
You can use the filters in the REST APIs wherever you want data from your relations. Eg: [include][relationName]
I think you can also pass data to the fields here.
https://docs.strongloop.com/display/public/LB/Where+filter
This might help you too
https://github.com/strongloop/loopback/issues/517

Can I use non-sequential id for loopback model?

Loopback uses sequential number for model ID. Can I use my own ID generator on server side? How do I go about doing that?
It is possible to specify Loopback generators (guid, uuid, ...) as a default function for id properties in your model definition file.
example with guid:
{
"name": "ModelName",
"base": "PersistedModel",
"idInjection": false,
"properties": {
"id": {
"type": "string",
"id": true,
"defaultFn": "guid"
}
},
"validations": [],
"relations": {},
"acls": [],
"methods": {}
}
As far as I know, you can't specify there your own default function yet. See related github issue.
If you want more advanced behavior (e.g. your own generator), you can create models/model-name.js file and extend a constructor of your model.
Yes, you would need to do a few things:
Set "idInjection": false in the corresponding model.json to turn off automatic id injection
Add the property you want to your model, then set it to be an id either by setting "id": true on the property in the model.json, or selecting the id radial next to the prop in the composer
Generate and inject the id, probably with an operation hook on before save (https://docs.strongloop.com/display/public/LB/Operation+hooks) or maybe a mixin (https://docs.strongloop.com/display/public/LB/Defining+mixins)
If you use Loopback 4 then this is the setting for generating UUID in prime key.
Inside you Model change this.
#property({
type: 'string',
id: true,
defaultFn: 'uuidv4',
})
id?: string;
This is the way to gen a unique id in your table.

Ember V1.0.0-pre.2: capitalization in handlebars templates

We are using Ember V1.0.0-pre.2 and our handlebars is as follows:
{{#each data.Product}}
<div>
{{Details.uid}} - {{Details.Name}}
</div>
{{/each}}
Our the 'data' bit is from this json:
{
"Product": [
{
"Details": {
"uid": "1",
"Name": "one"
}
},
{
"Details": {
"uid": "2",
"Name": "two"
}
},
{
"Details": {
"uid": "3",
"Name": "three"
}
},
{
"Details": {
"uid": "4",
"Name": "four"
}
},
{
"Details": {
"uid": "5",
"Name": "five"
}
}
]
}
This fails with the following warning:
WARNING: Watching an undefined global, Ember expects watched globals to be setup by the time the run loop is flushed, check for typos
When I change Details.whatever to details.whatever the warning disappears.
Is this by design or can we get around it somehow? The data is returned from the server in a fixed format and we wouldn't want to use another interim model if we can avoid it.
Ember has a naming policy where "instances/attributes" always start with a lowercase letter whilst "classes" always start with an uppercase letter. I think that's probably where you are running into some issues, if possible you should be de-serialising your JSON into attributes starting with lowercase letters.
Relevant part pulled from the guides (http://emberjs.com/guides/object-model/classes-and-instances/):
By convention, properties or variables that hold classes are capitalized, while instances are not. So, for example, the variable Person would contain a class, while person would contain an instance (usually of the Person class). You should stick to these naming conventions in your Ember applications.
Naming convention apply also to model data, but if you can't change what is coming from your API you can get around this by defining a map on a per property basis, e.g.
App.Adapter.map('App.Product', {
details: {key: 'Details'},
name: {key: 'Name'},
fooBar: {key: 'FOO_BaR'}
...
});
see here for more reference on how to map your json to your models: https://github.com/emberjs/data/blob/master/packages/ember-data/lib/system/mixins/mappable.js
hope it helps