How to set Invoice Tax Code in SuiteScript 2.1 - netsuite

I'm having some issues with setting the Tax Code on a Line Item related to an Invoice, this is the JSON for 1 of the Invoice Items I am passing to a RESTlet:
{
"item": {
"items": [
{
"taxCode": "8",
"quantity": 1,
"item": "7",
"description": "description",
"amount": 2280.00
}
]
}
}
The SuiteScript parses the JSON and sets the fields where necessary, I am able to set every other type of field, apart from the tax code, I have tried passing the Id as String and an Integer, as well as passing it as an object, like the below 2 examples, but I keep on getting errors no matter what I do.
"taxcode": {
"items": [
{ "id" : 8 }
]
}
"taxcode": {
{ "id" : 8 }
}
This is my RESTlet SuiteScript that iterates over the items and sets the relevant field values, as mentioned above; this is working for all other fields, it's just the tax code I am having issues with
for (let i of req[cust][key].items) {
// Select the sublist line
invoice.selectNewLine({
sublistId: key.toLowerCase()
});
// Iterate over the fields
for (let j in i) {
try {
// If the current field is an object
if (i[j] instanceof Object) {
// Get the subrecord
var child = invoice.getCurrentSublistSubrecord({
sublistId: key.toLowerCase(),
fieldId: j.toLowerCase()
});
// Set it's fields field
for (let k in i[j]) {
// Set the field and value
child.setValue({
fieldId: k.toLowerCase(),
value: i[j][k]
});
}
// Commit the line
invoice.setValue({
fieldId: j.toLowerCase(),
value: child
});
} else {
log.debug(
"setCurrentSublistValue",
JSON.stringify({
sublistId: key.toLowerCase(),
fieldId: j.toLowerCase(),
value: i[j]
})
);
// Set the fields
invoice.setCurrentSublistValue({
sublistId: key.toLowerCase(),
fieldId: j.toLowerCase(),
value: i[j]
});
}
} catch (e) {
log.debug(127, j);
log.debug(128, e);
}
}
// Commit the line
invoice.commitLine({
sublistId: key.toLowerCase()
});
}
Any ideas?

WORST API EVER!
You have to set the TaxCode last... or something else that is being set wipes it out -_-
Doesn't work:
{
"item": {
"items": [
{
"taxCode": "8",
"quantity": 1,
"item": "7",
"description": "description",
"amount": 2280.00
}
]
}
}
Works perfectly fine:
{
"item": {
"items": [
{
"quantity": 1,
"item": "7",
"description": "description",
"amount": 2280.00,
"taxCode": "8"
}
]
}
}

Related

Dynamodb scan on array of objects Filter Expression

I want to scan dynamodb using filter on product_id showing in below json of table.
Can anybody explain how to do scanning using filter of product_id.
Wants to scan dynamodb table data using documentclient.
Wants to find all fields which has product_id: something
{
"mandi_id": 1,
"product": [
{
"updated_price": 24,
"product_id": 2,
"last_price": 23
},
{
"updated_price": 24,
"product_id": 5,
"last_price": 23
}
],
"status": "active",
"createdAt": "2022-04-21T08:23:41.774Z",
"mandiCloseTime": "4pm",
"mandi_description": "anaj mandi",
"mandi_name": "gaziabad anaj mandi",
"state": "uttar pradesh",
"city": "gaziabad",
"main_image_s3": "",
"mandi_latlong": {
"lng": 77.48325609999999,
"lat": 28.680346
},
"mandiOpenTime": "10am",
"updatedAt": "2022-04-21T08:23:41.774Z",
"address_name": "gavindpuram",
"landmark_name": "mandi",
"village": "gaziabad",
"postal": "201013"
}
I have tried the following set of code but it is returning empty array list
var params = {
TableName: "dev-agrowave-mandi-management",
// Select: "ALL_ATTRIBUTES"
FilterExpression: "contains(#product,:product)",
ExpressionAttributeNames: {
"#product": "product",
},
ExpressionAttributeValues: { ":product": {"product_id":parseInt(id)}
}
};
let lastEvaluatedKey = 'dummy'; // string must not be empty
const itemsAll = [];
while (lastEvaluatedKey) {
const data = await docClient.scan(params).promise();
itemsAll.push(...data.Items);
lastEvaluatedKey = data.LastEvaluatedKey;
if (lastEvaluatedKey) {
params['ExclusiveStartKey'] = lastEvaluatedKey;
}
}
return {msg:itemsAll,params:params};

elasticsearch node.js API remove an object from an array on a document using painless script results in array Index Out of Bounds

I want to remove items (an object) from an array on a document in elasticsearch, however whenever I try and run my update script using painless, I receive an Array Index Out of Bounds exception.
I'm using the javascript elasticsearch npm package to search elasticsearch for the relevant documents which then returns me data like:
"_index": "centres",
"_type": "doc",
"_id": "51bc77d1-b514-4f4e-85fa-412def6829f5",
"_score": 1,
"_source": {
"id": "cbaa7daa-f1a2-4ac3-8d7c-fc981245d21c",
"name": "Five House",
"openDays": [
{
"title": "new open Day",
"endDate": "2022-03-22T00:00:00.000Z",
"id": "82be934b-eeb1-419c-96ed-a58808b30df7"
},
{
"title": "last open Day",
"endDate": "2020-12-24T00:00:00.000Z",
"id": "8cc339b9-d2f8-4252-b68a-ed0a49cbfabd"
}
]
}
I then want to go through and remove certain items from the openDays array. I've created an array of the items I want to remove, so for the above example:
[
{
id: '51bc77d1-b514-4f4e-85fa-412def6829f5',
indexes: [
{
"title": "last open Day",
"endDate": "2020-12-24T00:00:00.000Z",
"id": "8cc339b9-d2f8-4252-b68a-ed0a49cbfabd"
}
]
}
]
I'm then trying to run an update via the elasticsearch node client like this:
for (const centre of updates) {
if (centre.indexes.length) {
await Promise.all(centre.indexes.map(async (theIndex) => {
const updated = await client.update({
index: 'centres',
type: 'doc',
id: centre.id,
body: {
script: {
lang: 'painless',
source: "ctx._source.openDays.remove(ctx._source.openDays.indexOf('openDayID'))",
params: {
"openDayID": theIndex.id
}
}
}
}).catch((err) => {throw err;});
}))
.catch((err) => {throw err;});
await client.indices.refresh({ index: 'centres' }).catch((err) => { throw err;});
}
}
When I run this though, it returns a 400 with an "array_index_out_of_bounds_exception" error:
-> POST http://localhost:9200/centres/doc/51bc77d1-b514-4f4e-85fa-412def6829f5/_update
{
"script": {
"lang": "painless",
"source": "ctx._source.openDays.remove(ctx._source.openDays.indexOf(\u0027openDayID\u0027))",
"params": {
"openDayID": "8cc339b9-d2f8-4252-b68a-ed0a49cbfabd"
}
}
}
<- 400
{
"error": {
"root_cause": [
{
"type": "remote_transport_exception",
"reason": "[oSsa7mn][172.17.0.2:9300][indices:data/write/update[s]]"
}
],
"type": "illegal_argument_exception",
"reason": "failed to execute script",
"caused_by": {
"type": "script_exception",
"reason": "runtime error",
"script_stack": [],
"script": "ctx._source.openDays.remove(ctx._source.openDays.indexOf(\u0027openDayID\u0027))",
"lang": "painless",
"caused_by": {
"type": "array_index_out_of_bounds_exception",
"reason": null
}
}
},
"status": 400
}
I'm not quite sure where I'm going wrong with this. Am I using the indexOf painless script correctly? Does indexOf allow for the searching of properties on objects in arrays?
I stumbled across this question and answer: Elasticsearch: Get object index with Painless script
The body of the update script needs changing like so:
Promise.all(...
const inline = `
def openDayID = '${theIndex.id}';
def openDays = ctx._source.openDays;
def openDayIndex = -1;
for (int i = 0; i < openDays.length; i++)
{
if (openDays[i].id == openDayID)
{
openDayIndex = i;
}
}
if (openDayIndex != -1) {
ctx._source.openDays.remove(openDayIndex);
}
`;
const updated = await client.update({
index: 'centres',
type: 'doc',
id: centre.id,
body: {
script: {
lang: 'painless',
inline: inline,
},
}
}).catch((err) => {throw err;});
await client.indices.refresh({ index: 'centres' }).catch((err) => { throw err;});
})).catch(... //end of Promise.all
I am not au fait with painless scripting, so there are most likely better ways of writing this e.g. breaking once the index of the ID is found.
I have also had to move the refresh statement into the Promise.all since if you're trying to remove more than one item from the array of objects, you'll be changing the document and changing the index. There is probably a better way of dealing with this too.
'openDayID' should be params.openDayID
And use removeIf:
"ctx._source.openDays.removeIf(el -> (el.id == params.openDayID))"

Use ONLY the external id of an item to create an invoice in Netsuite using Suitescript

Is it possible to create an invoice using item's external id and not internal id using a Restlet? I can accomplish this in Postman like this:
"item": {
"items": [
{
"amount": 120.0,
"item": {
"externalid": "12878"
},
"taxCode": {
"id": "13"
}
}
]
}
But when I try to set the same in Restlet, it throws an error.
var currentItem = items[i];
record.selectNewLineItem('item');
record.setCurrentLineItemValue('item', 'externalid', currentItem["exId"]);
record.setCurrentLineItemValue('item', 'quantity', currentItem["quantity"]);
record.setCurrentLineItemValue('item', 'rate', currentItem["rate"]);
record.setCurrentLineItemValue('item', 'taxcode', currentItem["taxcode"]);
record.commitLineItem('item');
{"error":{"code":"INVALID_KEY_OR_REF","message":"Invalid item reference key 12878 for subsidiary 1."}}
What you'd need to do is search for the items by external id.
var extIds = items.map(function(it){ return it.exId});
var items = nlapiSearchRecord('item', null, [
new nlobjSearchFilter('externalid', null, 'anyof', extIds)
], [
new nlobjSearchColumn('externalid')
]);
// check for null return and throw error
var extIdMap = {};
items.forEach(function(ref){
extIdMap[ref.getValue('externalid')] = ref.getId();
});
//then instead of record.setCurrentLineItemValue('item', 'externalid', currentItem["exId"]);
record.setCurrentLineItemValue('item', 'item', extIdMap[currentItem["exId"]]);

Accessing sub lists from netsuite

I'm trying to access the json data in the format liike below...
{"subscriptions":
"recmachcustrecord2": [{
"custrecord_acceptable_min_shelf_life": "60",
"custrecord_item": {
"internalid": "399",
"name": "ABS2002-PACK"
}
}, {
"custrecord_acceptable_min_shelf_life": "60",
"custrecord_item": {
"internalid": "400",
"name": "ABS2003-PACK"
}
}]
}
I have written like
var subrec = salesRepRec.getSublistSubrecord({
sublistId: 'recmachcustrecord2',
fieldId: 'custrecord_item',
line: 0
});
{"type":"error.SuiteScriptError","name":"FIELD_1_IS_NOT_A_SUBRECORD_FIELD","message":"Field custrecord_item is not a subrecord field.","stack":["anonymous(N/serverRecordService)","onAfterSubmit(/SuiteScripts/cus.js:23)"],"cause":{"type":"internal error","code":"FIELD_1_IS_NOT_A_SUBRECORD_FIELD","details":"Field custrecord_item is not a subrecord field.","userEvent":"aftersubmit","stackTrace":["anonymous(N/serverRecordService)","onAfterSubmit(/SuiteScripts/cus.js:23)"],"notifyOff":false},"id":"","notifyOff":false,"userFacing":false}
mainly i want access the "internalid": "400",
"name": "ABS2003-PACK" these fields.
how can i access the using the suite script 2.0
Thanks in Advance!
AFAIK NetSuite does not allows creating a custom sublist subrecord. Although in you case, you only need to fetch internalid and itemid from the subrecord which can be achieved as below
{
custrecord_item: {
internalId: salesRepRec.getSublistValue({ sublistId: 'recmachcustrecord2', fieldId: 'custrecord_item', line: 0 }),
name: salesRepRec.getSublistText({ sublistId: 'recmachcustrecord2', fieldId: 'custrecord_item', line: 0 })
}
}

Mongo find the max value of an attribute in an array of objects and return the entire matching object

I am working on application having NodeJS on server-side and MongoDB as database and Mongoose as ORM.
Below is my document in mongo collection.
{
"rec_id": 73282,
"process_id": 73272,
"is_cancelled": false,
"process_status_progress": [
{
"state": {
"state_number": 1,
"state_name": "Step 1"
},
"last_update_date": 1499773230587,
"state_error": {}
},
{
"state": {
"state_number": 2,
"state_name": "Step 2"
},
"last_update_date": 1499773246295,
"state_error": {}
},
{
"state": {
"state_number": 3,
"state_name": "Step 3"
},
"last_update_date": 1499773508526,
"state_error": {
"error_message": "Some error message",
"error_details": {
"key": "value"
}
}
}
],
"job_status": "Step 3"
}
I am executing below query (which selects documents for which max progress state is less than state number 9):
db.processes.aggregate([
{
"$project": {
"maxState": {
"$max": "$process_status_progress.state.state_number"
},
"rec_id": 1,
"process_id": 1
}
},
{
"$match": {
"$or": [
{
"maxState": {
"$lt": 9
}
}
]
}
}
])
This returns me following output:
{ "rec_id": 1494929214467, "process_id": 1494929214501,
"maxState": 3 }
"state_error" object will have keys "error_message" and "error_details" if any error is there in that state while processing and "state_error" will not be blank.
Objects will be added into "process_status_progress" as process is processing further. I have just shown sample data above. So document may have more objects in "process_status_progress" array field.
How can I return whole object from process_status_progress which is having max value for state number and state_error having any data like below?
{ "rec_id": 1494929214467, "process_id": 1494929214501,
"maxState": 3, "maxStateObj": {
"state": {
"state_number": 3,
"state_name": "Step 3"
},
"last_update_date": 1499773508526,
"state_error": { "error_message" : "Some error message", "error_details" : {"key" : "value"}} } }
That means I want to fetch documents for which max state (less than provided state number. In this case, it is 9) is having error and fetch that object which is inside "process_status_progress" as well.
Can I achieve this in single Mongo query or I have to fetch data and then write loop for processing that data?

Resources