Loopback framework always expecting the input field names as lowercase - loopbackjs

We are implementing the Database connector with Loopback framework. Database fields are case-insensitive. Loopback framework creating the model with all table fields and properties as lowercase characters. When we invoke create or update operation with field names as uppercase, it's throwing the input validation errors.
{
"error": {
"name": "ValidationError",
"status": 422,
"message": "The `TEST5` instance is not valid. Details: `name` can't be blank (value: undefined).",
"statusCode": 422,
"details": {
"context": "TEST5",
"codes": {
"name": [
"presence"
]
},
"messages": {
"name": [
"can't be blank"
]
}
},
"stack": "ValidationError: The `TEST5` instance is not valid. Details: `name` can't be blank (value: undefined).\n at ..node_modules\\loopback-datasource-juggler\\lib\\dao.js:211:16\n at ModelConstructor. (..node_modules\\loopback-datasource-juggler\\lib\\validations.js:462:11)\n
}
}

Use .observe with "before save" hook. Then loop through properties converting to lower case. Before save with observe hits before validation too

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 :)

DRF: Set ChoiceField default programmatically from DB query

I asked a similar question here about setting the default value of a TextChoices field on a model. Now I'm taking it to the next level.
I've moved the choices settings from the model to the serializer ChoiceField. The site is Django/DRF/django_tenants backend with Vue frontend. I want the front/backends to be using the same set of choices and, just as important, the same default values. So I created an OptionGroup table. Here are two sample rows from that table (some options omitted):
{
"results": {
"id": 1,
"name": "payment_method",
"defined_in": "option_table",
"default_option": "5",
"options": [
{
"id": 2,
"name": "Bank Transfer",
"value": "2"
},
{
"id": 5,
"name": "Credit Card",
"value": "5"
},
{
"id": 8,
"name": "PayPal",
"value": "8"
}
]
}
}
{
"results": {
"id": 3,
"name": "invoice_type",
"defined_in": "class",
"app_label": "invoices",
"choices_class": "InvoiceType",
"default_option": "standard",
"options": [
{
"name": "Standard",
"value": "standard"
},
{
"name": "Retainer",
"value": "retainer"
},
{
"order": 1,
"name": "Estimate",
"value": "estimate"
}
]
}
}
The first one (defined_in = "option_table") has its options defined in a related Option model. The second one has its options defined in a subclass of TextChoices in the backend code. In addition to keeping the front/backend in sync for options and default values, this will also allow users to set which option for each select list field they want as the default value. Note the default_option field above.
I created a class, extended from the ChoiceField class (from DRF), and added logic to the __init__() method to get the default value from the OptionGroup model and set it for the serializer field being defined.
class CustomChoiceField(serializers.ChoiceField):
def __init__(self, choices, **kwargs):
option_group = kwargs.pop('option_group', None)
if option_group and 'default' not in kwargs:
group = OptionGroup.objects.filter(name__iexact=option_group)
if group and group.default_option:
kwargs['default'] = group.default_option
super().__init__(choices, **kwargs)
And this is how it is being used:
type = CustomChoiceField(
choices=choices.InvoiceType.choices,
option_group='invoice_type',
)
The problem is that the active schema at that point is "public" instead of the actual tenant schema. It seems the __init__() for my custom class is being executed too early in the request process - before django_tenants has connected to the proper schema.
Does anyone have a suggestion as to how this can be accomplished, or is what I'm trying to do just not possible?

DynamoDB LIKE '%' (contains) search over an array of objects using a key from the object, NodeJS

I am trying to use a "LIKE" search on DynamoDB where I have an array of objects using nodejs.
Looking through the documentation and other related posts I have seen this can be done using the CONTAINS parameter.
My question is - Can I run a scan or query over all of my items in DynamoDB where a value in my object is LIKE "Test 2".
Here is my DynamoDB Table
This is how it looks as JSON:
{
"items": [
{
"description": "Test 1 Description",
"id": "86f550e3-3dee-4fea-84e9-30df174f27ea",
"image": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/86f550e3-3dee-4fea-84e9-30df174f27ea.jpg",
"live": 1,
"status": "new",
"title": "Test 1 Title"
},
{
"description": "Test 2 Description",
"id": "e17dbb45-63da-4567-941c-bb7e31476f6a",
"image": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/e17dbb45-63da-4567-941c-bb7e31476f6a.jpg",
"live": 1,
"status": "new",
"title": "Test 2 Title"
},
{
"description": "Test 3 Description",
"id": "14ad228f-0939-4ed4-aa7b-66ceef862301",
"image": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/14ad228f-0939-4ed4-aa7b-66ceef862301.jpg",
"live": 1,
"status": "new",
"title": "Test 3 Title"
}
],
"userId": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
}
I am trying to perform a scan / query which will look over ALL users (every row) and look at ALL items and return ALL instances where description is LIKE "Test 2".
I have tried variations of scans as per the below:
{
"TableName": "my-table",
"ConsistentRead": false,
"ExpressionAttributeNames": {
"#items": "items",
},
"FilterExpression": "contains (#items, :itemVal)",
"ExpressionAttributeValues": {
":itemVal":
{
"M": {
"description": {
"S": "Test 2 Description"
},
"id": {
"S": "e17dbb45-63da-4567-941c-bb7e31476f6a"
},
"image": {
"S": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/e17dbb45-63da-4567-941c-bb7e31476f6a.jpg"
},
"live": {
"N": "1"
},
"status": {
"S": "new"
},
"title": {
"S": "Test 2 Title"
}
}
}
}
}
The above scan works but as you can see I am passing in the whole object as an ExpressionAttributeValues, what I want to do is just pass in the description for example something like the below (which doesnt work and returns no items found).
{
"TableName": "my-table",
"ConsistentRead": false,
"ExpressionAttributeNames": {
"#items": "items.description",
},
"FilterExpression": "contains (#items, :itemVal)",
"ExpressionAttributeValues": {
":itemVal":
{
"S": "Test 2"
}
}
}
Alternatively, would it be better to create a separate table where all the items are added and they are linked via the userId? I was always under the impression there should be one table per application but in this instance I think if I had all the item data at the top level, scanning it would be a lot safer and faster.
So with nearly 200 views since posting and no responses I have come up with a solution that does not immediately solve the initial problem (I honestly do not think it can be solved) but have come up with an alternative approach.
Firstly I do not want two tables as this seems overkill, and I do not want the aws costs associated with two tables.
This has lead me to restructure the primary keys with prefixes which I can search over using the "BEGINS_WITH" dynamodb selector query.
Users will be added as U_{USER_ID} and items will be added as I_{USER_ID}_{ITEM_ID}, this way I only have one table to manage and pay for and this allows me to run BEGINS_WITH "U_" to get a list of users or "I_" to get a list of items.
I will then flatten the item data as strings so I can run "contains" searches on any of the item data. This also allows me to run a "contains {USER_ID}" search on the primary keys for items so I can get a list of items for a particular user.
Hope this helps anyone who might come up against the same issue.

How can I get the attribute value based on sibling attribute value from a json response?

This is my response.
[
{
"id": 123,
"name": "text1"
},
{
"id": 456,
"name": "text2"
},
{
"id": 789,
"name": "text3"
}
]
I can just provide the name value and want to get back the id attribute. I am using rest assured. I can create a map and then get it accordingly but searching for solutions like jsonPath().get(id where name ="text2"). Just thinking if anything can be done like that.
You can use conditions like .find{it.name=='text2'}.id

HasMany relationships between sideloaded models

Here's my Ember-Data model:
Lrt.Option = DS.Model.extend({
option_relation_value: hasMany('option')
});
Here is an example of the JSON: (Shortened for the sake of this question)
{
"optionGroups": [],
"optionSubGroups": [
{
"id": "3",
"optionType": [
"80",
"81",
"82",
"83",
"84",
"248",
"278"
],
"title": "Option Group for 80"
}
],
"options": [
{
"id": "45",
"option_relation_value": [
"80"
]
},
{
"id": "80",
"option_relation_value": []
}
]
}
There are also "OptionGroup" and "OptionSubGroup" models which are sideloading options in.
The issue I'm having is that after adding in the 'hasMany' into the model, I can no longer do query the store for Options like this:
this.get('store').find('option')
It simply returns "0", however in the Ember Inspector, I get 400+ entries so I know the data loaded.
When using the chrome inspector and break on ALL Exceptions, it breaks on line 2246 of Ember-Data at the following line:
2246: Ember.assert('The id ' + id + ' has already been used with another record of type ' + type.toString() + '.', !id || !idToRecord[id]);
The error is:
"Cannot call method 'toString' of undefined"
"type" in this line is 'undefined'.
What am I doing wrong with this hasMany relationship?
I am using Ember-Data 1.0 Beta 2.
Technically, this is not side loading, it's really more like nested loading. That may have something to do with it.
For true side loading you'd want a structure like this as your outer SON response :
{
"option" : {
"id" : 3,
...
"options" : [45,80]
}
"options" : [
{ "id":45 , ... },
{ "id":80 , ... }
]
}
Here are the docs about JSON conventions : http://emberjs.com/guides/models/connecting-to-an-http-server/#toc_json-conventions The comments are an example of side loading.
I know that this works for separate model structures (post -> comment), but I'm not sure about self referential tree type structures.