PnPJS update items - List data validation failed - sharepoint

We loaded a SP list directly from an Access query and now when we try to run a list update with pnpjs I get an "Error code: -2130575163.List data validation failed" .
There are no required fields, no validation on any columns, and no Validation settings on the list. Is this not working because it was uploaded from Access?
Updating it similar to this:
const items = await sp.web.lists.getByTitle("MyList").items.top(1).filter("Title eq 'A Title'").get();
const updatedItem = await sp.web.lists.getByTitle("MyList").items.getById(items[0].Id).update({
my_id: mynewID,
})
Adding list items works with no issues. Updating a list item does not work.

Try this.
let list = sp.web.lists.getByTitle("MyList");
const i = await list.items.getById(1).update({
Title: "My New Title",
Description: "Here is a new description"
});
console.log(i);

Is items[0].Id valid ?
Please try to use console.log (items[0].Id) to check in Developer Tool.
I tested the same request in my side, my_id is a number field:
const items = await sp.web.lists.getByTitle("JqueryList").items.top(1).filter("Title eq 'My New Title'").get();
console.log(items);
let list = sp.web.lists.getByTitle("JqueryList");
const i = await list.items.getById(items[0].Id).update({
Title: "My New Title",
my_id: 1
});

I did resolve it - when you use the StrReverse function in Access and then upload that query to a SP list - the list type is corrupted.
To fix it I simply went in and changed the type from single line text to multiline - then back to single line of text.
I was then able to update the list item.

Related

Firebase function - how to create multiple documents from different collections

I am fairly new to writing functions and cannot figure out how to solve my issue or even search for it properly.
I have three collections:
current_projects
vendors
vendor_projects
when a new project is created I want the function to take all documents in vendors, add certain fields from them to vendor_projects, and include the project_id field that is created in current_projects.
Do I need a for loop to accomplish this or is there other syntax that could be utilized?
My current function is below. This creates on document using the new project_id field but doesnt take any of the fields from vendors. Any input is greatly appreciated.
exports.createProjVen = functions.firestore.document("/Current_projects/{id}")
.onCreate((snap, context)=>{
console.log(snap.data());
const id = snap.data().id;
// const collection = context.params.Current_projects;
// const id = context.params.id;
const projectVendors = admin.firestore().collection("project_vendors");
// const vendors = admin.firestore().collection("vendors");
return projectVendors.doc(id).set({
actual: "",
budget: "",
id: "23121",
project_id: id,
toggle: "true",
type: "Fixtures",
vendor_company: "tes",
vendor_contact: "tes",
vendor_email: "jj#j.com",
vendor_id: "test",
vendor_phone_number: "test"});
});
Adding more details:
When a new project is added it creates a record in current_projects.
I want the function to be able to query all documents in the vendor collection when a new record is created in current_projects.
From there, I want to grab the highlighted fields from the vendor documents, add the id from that was created from current_projects (highlighted in the first screen shot), and create a new document in project_vendors (third screen shot below) for every document in the vendors table.
If you are trying to created a document in project_vendors collection for every vendor in vendors after a project is created then you can map an array of promises and then use Promise.all() as shown below:
exports.createProjVen = functions.firestore.document("/Current_projects/{id}")
.onCreate((snap, context) => {
const docSnap = snap.data();
const id = context.params.id;
const vendorsSnap = await admin.firestore().collection("vendors").get();
const vendorsData = vendorsSnap.docs.map((d) => ({ id: d.id, ...d.data() }))
const promises = [];
const vendorPrsCol = admin.firestore().collection("project_vendors");
vendorsData.forEach((vendor) => {
const data = {
projectId: id,
email: vendor.email,
// other vendor fields
}
promises.push(vendorPrsCol.add(data));
})
await Promise.all(promises);
console.log("Vendor Projects added");
return null;
});

Using Suitescript, can I find a record related to my current without N/search?

I'm trying to delete a record that is related to the current record loaded using a workflow action script. I've seen other answers to similar questions saying that I can find the internal ID of the related record with a search using the value in the key field as the search parameter. Problem: The N/search module is not available in a workflow action script, which is where I'm currently coding.
To make the question more concrete, my user has pulled up a general ledger account record ('account'), and they're going to delete it. I have an NS bundle that functions as an integrator with a 3rd party piece of software. The NS bundle has a value transformation table that maps the NS account codes to the 3rd party software codes. Each value transformation lives in a custom record ('icvt') created by the bundle, and I need the value transformation record deleted. I was hoping to use N/search to look up the icvt record, but I CAN'T USE SEARCH in a workflow action script.
Help.
Edit: Just realized I think I misunderstood the documentation, and that N/search is available, so my error must be somewhere else.
Edit to add code. This is the search code I was using before I realized the module wasn't available to me:
/**
*#NApiVersion 2.x
* #NScriptType WorkflowActionScript
*/
// Deletes Value Transform related to account deleted.
define(['N/record', 'N/search', 'N/log'], function (record, search, log) {
function wfDeleteICVT(scriptContext) {
var deleted_account = scriptContext.newRecord;
var da_internalID = deleted_account.getValue("id");
var v_da_internalID = da_internalID.toString();
var mySearch = search.create({
type: 'icvt',
filters: [
search.createFilter({
name: 'sourcevalue',
operator: search.Operator.IS,
values: v_da_internalID
})
]
});
//log.debug(v_da_internalID)
var myResultSet = mySearch.run();
var myResultRange = myResultSet.getRange(0,1);
log.debug({title: myResultRange.length, details: myResultSet})
var deleted_icvt = mySearch[0];
var di_icvt = deleted_icvt.id;
deleted_icvt.delete({
type: 'icvt',
id: di_internalID
});
}
return {
onAction : wfDeleteICVT
}
});
If you are able to fetch the ID of the record that needs to be deleted, you can use N/record module with record.delete(options) to delete the desired record.
// Delete a sales order.
var salesOrderRecord = record.delete({
type: record.Type.SALES_ORDER,
id: 88,
});
// Delete an instance of a custom record type with the ID customrecord_feature.
var featureRecord = record.delete({
type: 'customrecord_feature',
id: 3,
});
EDIT-
N/search module works on Workflow Action Scripts. I myself have used it many times. Why don't you create the Saved Search in UI on Netsuite and then Export it as script and use it in your script?
To export - You can use the Chrome extension below.
NetSuite Search Export
Also, I can see you have created filters in your search.create method but you didn't add any columns. That might be the issue.
Let me know.
Here's the final solution that worked. I was completely wrong in my initial assumptions that I couldn't use search, so that was the ultimate solution, although I did take #sayeesh's advice and use a search created through the UI:
/**
*#NApiVersion 2.x
* #NScriptType WorkflowActionScript
*/
// Deletes Value Transform related to account deleted.
define(['N/record', 'N/search', 'N/log'], function (record, search, log) {
function icvtDelete(scriptContext) {
var deleted_account = scriptContext.newRecord; //gets the account record of the current account
var da_internalID = deleted_account.getValue("id"); //gets the internal id of the current account
var v_da_internalID = da_internalID.toString(); //converts the internal id to a string for comparison later
var mySearch = search.load({
id: "customsearch_icvt_search"}); //loads a saved search
var mySearchResult = mySearch.run(); //runs the saved search
var myResults = mySearchResult.getRange(0,1000); //gets the range of results
for(var i in myResults){ //iterates through the results
var result = myResults[i]; //load a result
if(result.getValue('custrecordictransformationvalue') == v_da_internalID) //if the result is the one we're looking for
{
var icvt_to_delete = record.load({
type: 'mycustomrecord',
id: result.getValue('id')
});
log.debug(v_da_internalID, result.getValue('id'));
icvt_to_delete.setValue({fieldId: 'deletionreason', value: 1});
icvt_to_delete.setValue({fieldId: 'deletionreasonmemo', value: 'SS2.0 Delete reason saved using Load/Save'});
icvt_to_delete.save();
record.delete({
type: 'mycustomrecord',
id: result.getValue('id')
});
}
}
}
return {
onAction : icvtDelete
}
});

How do I copy entries from one collection to another using mongoose?

I'm trying to create a little task management site for a work project. The overall goal is here is that the tasks stay the same each month (their status can be updated and whatnot), and they need to be duplicated at the start of each new month so they can be displayed and sorted by on a table.
I already figured out how to schedule the task, I have the table I need set up. A little explanation before the code - the way I'm planning on doing this is having two different task collections - one I've called "assignments", will have the tasks that need to be duplicated (with their description, status and other necessary data) and another collection, which I called "tasks", will have the exact same data but with an additional "date" field. This is where the table will get it's data from, the date is just for sorting purposes.
This is what I have so far -
Index.js: gets all the assignments from the database, and sends the object over to the duplicate function.
router.get('/test', async function(req, res, next) {
let allTasks = await dbModule.getAllAssignments();
let result = await dbModule.duplicateTasks(allTasks);
res.json(result);
});
dbmodule.js:
getAllAssignments: () => {
allAssignments = Assignment.find({});
return allAssignments;
},
duplicateTasks: (allTasksToAdd) => {
try {
for (let i = 0; i < allTasksToAdd.length; i++) {
let newTask = new Task({
customername: allTasksToAdd.customername,
provname: allTasksToAdd.provname,
description: allTasksToAdd.description,
status: allTasksToAdd.status,
date: "07-2020"
})
newTask.save();
}
return "Done"
} catch (error) {
return "Error"
}
}
The issue arises when I try and actually duplicate the tasks. For testing purposes I've entered the date manually this time, but that's all that ends up being inserted - just the date, the rest of the data is skipped. I've heard of db.collection.copyTo(), but I'm not sure if it'll allow me to insert the field I need or if it's supported in mongoose. I know there's absolutely an easier way to do this but I can't quite figure it out. I'd love some input and suggestions if anyone has any.
Thanks.
The problem is that allTasksToAdd.customername (and the other fields your trying to access) will be undefined. You need to access the fields under the current index:
let newTask = new Task({
customername: allTasksToAdd[i].customername,
provname: allTasksToAdd[i].provname,
description: allTasksToAdd[i].description,
status: allTasksToAdd[i].status,
date: "07-2020"
})
Note that you can simplify this by using a for .. of loop instead:
for (const task of allTasksToAdd) {
const newTask = new Task({
customername: task.customername,
provname: task.provname,
description: task.description,
status: task.status,
date: "07-2020"
});
newTask.save();
}

record.tranform Transfer Order to Item Receipt throws error

I'm trying to create an item receipt from a transfer order. I am able to transform the record but when I go to save it I get the error
You must enter at least one line item for this transaction.
My code is
var data = JSON.parse(params.data);
//get tranfser order
var lookupResults = search.lookupFields({
type : search.Type.ITEM_FULFILLMENT,
id : data.id,
columns : 'createdfrom'
});
var transferOrderId = lookupResults.createdfrom;
log.debug("Transfer Order", JSON.stringify(lookupResults.createdfrom));
//Create Item Receipt from transfer order
var itemReceipt = record.transform({
fromType : record.Type.TRANSFER_ORDER,
fromId : transferOrderId[0].value,
toType : record.Type.ITEM_RECEIPT
});
log.debug("Data", JSON.stringify(itemReceipt));
itemReceipt.save({
ignoreMandatoryFields : true
});
The log for Data shows that there are Lines for this item receipt. But for some reason NetSuite throws the error. What am I doing wrong?
You probably have to check itemreceive on each item line you want to receive. Also make sure you are dealing with a shipped fulfillment

SuiteScript 2.0 Transaction Saved Search Filter

I have created a saved search for transaction in netsuite and with suitescript 2.0 I am showing saved search data in my application. In application user can apply filter on any fields (please see the attached screenshot). For example user select "Aug 2011" for posting period, only transactions of Aug 2011 should be loaded. This works fine if I create a filter with internalid of "Aug 2011", but on UI I dont have internal id.
sample code:
/*
here is my required module
*/
function getTransactionData(datain)
{
try
{
var objSearch = search.load
({
id: datain.savedsearchid
});
/***** Work *****/
objSearch.filters.push(search.createFilter({ name: "postingperiod", operator: "ANYOF", values: "1" })); //here 1 is internalid of periodname "Aug 2011"
/***** Not Work (SSS_INVALID_SRCH_FILTER_JOIN) *****/
//objSearch.filters.push(search.createFilter({ name: "postingperiod", join: "accountingperiod", operator: "ANYOF", values: "Aug 2011" }));
objSearch.run();
}
catch(ex)
{
log.error("getTransactionData", ex);
throw ex;
}
}
I tried with join but seeing "SSS_INVALID_SRCH_FILTER_JOIN" error from Netsuite.
Can any one please help me regarding this.
Thanks in advance
I edited your code to a more simplified one to understand better.
If you get the gist of how it works, you can edit/customize the way you want.
I assume there is join 'accountingperiod' option available for 'postingperiod' and this works perfectly in your saved search you created in netsuite without using suitescript.
/*
here is my required module
*/
function getTransactionData(datain) {
try {
var objSearch = search.load({
id: datain.savedsearchid
});
var defaultFilters = objSearch.filters;
var customFilters = [];
//Adding filter
customFilters = ['postingperiod', 'ANYOF', '1'];
defaultFilters.push(customFilters);
customFilters = undefined;
customFilters = [];
//Adding filter
/*
customFilters = ['postingperiod.accountingperiod', 'ANYOF', 'Aug 2011'];
defaultFilters.push(customFilters);
*/
objSearch.filters = defaultFilters;
var objSearch_run = objSearch.run().getRange({
start: 0,
end: 10
});
} catch (ex) {
log.error("getTransactionData", ex);
throw ex;
}
}
If you want to know how filters is stored in saved search you created in netsuite, you can use the script debugger.
The following code is suitescript 1.0
//Load Saved Search
get();
function get() {
var search = nlapiLoadSearch('transaction', ' ENTER SAVED SEARCH ID HERE ');
log.debug('search',search);
var searchFilters = search.getFilterExpression();
log.debug('searchFilters',searchFilters);
return search;
}
I assume your application is a Suitelet? If so, you need to do a select field type of your record. So probably of 'posting periods'. This will show your periods in a drop down.
When the user selects it, have a client side script auto refresh the data and load your saved search.
Alternatively, you can load all the data and do the filtering client side DOM filtering. Really need a bit more information about your "application".

Resources