xPages REST service to feed a Notes Calendar Store - xpages

I am trying to use RESTservice to get data from a resource reservation DB and provide a calendar with filter capability by resource name.
All run fine while I use the rest service without filter
<xe:restService id="restService2" pathInfo="/inoteslegacyjson">
<xe:this.service>
<xe:viewJsonLegacyService count="30000"
databaseName="${compositeData.databaseName}"
viewName="${compositeData.viewName}" defaultColumns="false"
var="entry" contentType="text/plain" compact="false">
<xp:this.columns>
<!-- Cal Date -->
<xe:restViewColumn name="$134"
columnName="StartDateTime">
</xe:restViewColumn>
<!-- Icon -->
<xe:restViewColumn name="$149" columnName="$149"></xe:restViewColumn>
<!-- Start Date -->
<xe:restViewColumn name="$144"
columnName="StartDateTime">
</xe:restViewColumn>
...
But when I put a search syntax like this:
<xe:this.search><![CDATA[#{javascript:
var isResourceFiltered:Boolean;
var strTmp:String=viewScope.resourceName;
isResourceFiltered=(strTmp.compareToIgnoreCase("All")!=0);
print ("Is result filtered:" + isResourceFiltered + ", filter: "+ strTmp);
if (!isResourceFiltered) {
return "";
}
return "ResourceName=" + viewScope.resourceName}]]></xe:this.search>
I cannot see any message in console about Print() and get some errors in page:
calendarDataStore: RequestError: Unable to load /admin/resource.nsf/ResourceCalendarFiltered.xsp/inoteslegacyjson status: 500
or error 400
How does can I filter a calendar view for resource name
(And how make a time slice to get only time period showed in the UI to avoid count="30000"?)

viewScope.resourceName may not be set early enough for it to be used. This could explain the lack of a print statement and the error 500 returned by the calendarDataStore.
Try adding some error handling to verify it's an issue with the component vs an error with your code.
XPages OpenLog Logger (or the corresponding code in OpenNTF Domino API) will catch uncaught exceptions and so would verify coding issues without needing try/catch blocks.

I did a Java Rest service and used FT Search to search between two date ranges. You could also work your search by resource name into that FT Search as well. In my case I did not use a view but did the lookup in Java and built the returned text in my code (to work with FullCalendar, a web based calendar). Works great and is fast.

Related

Netsuite Invalid API usage. You must use getValue to return the value set with setValue

So I have an odd issue, When I create a new transaction and save, this error in the title gets thrown. But when I edit this transaction after it was created, the getText does not throw this error. Is there something I'm doing wrong or something special needed to getText on a create new record? Here is my code. This is for the afterSubmit method on my User Event Script for Vendor Bill screen. I just noticed getValue does work on create, does not produce this error, just don't understand why? Is this the correct way to get the value on create? To use getValue and getText cannot be used on create? Only for edit?
if (scriptContext.type == scriptContext.UserEventType.CREATE ||
scriptContext.type == scriptContext.UserEventType.EDIT) {
// get bill to index
var Bill = scriptContext.newRecord;
// fails on this call below on create but works on edit
var refno = Bill.getText({ fieldId: 'tranid' });
}
This behavior is described in the API documentation here.
In dynamic mode, you can use getText() without limitation but, in standard mode, limitations exist. In standard mode, you can use this method only in the following cases:
You can use getText() on any field where the script has already used setText().
If you are loading or copying a record, you can use getText on any field except those where the script has already changed the value by using setValue().
Apparently the newRecord object falls under the second criteria. At this point, the object only has values set. tranid will have a value with the transaction's internal ID, but it won't have the transaction name stored. To get the text, you will have to use record.load() to get the full record, or use search.lookupFields() to get just the transaction name.

How do I create a composite index for my Firestore query?

I'm trying to perform a firestore query on a collection which results in a failure because an index needs to be created for the query I'm attempting. The error contains a link that is suppose to auto create the missing index for me. However when I follow the link and attempt to create the index that has been prepared for me I encounter an error stating "name only indexes are not supported". I would also point out I have been using the npm functions-framework to test my cloud function that contains the relevant query.
I have tried creating the composite index myself manually but none of the index I have made seem to satisfy my attempted query.
Sample docs in my Items Collection:
{
descriptionLastModified: someTimestamp <a timestamp datatype>
detectedLanguage: "en-us" <string>
}
{
descriptionLastModified: someTimestamp <a timestamp datatype>
detectedLanguage: "en-us" <string>
}
{
descriptionLastModified: someTimestamp <a timestamp datatype>
detectedLanguage: "fr" <string>
}
{
descriptionLastModified:someTimestamp <a timestamp datatype>
detectedLanguage: "en-us" <string>
}
These are all queries I have tried which fail:
let queryRef = itemsRef.where('descriptionLastModified','<=', oneDayAgoTimestamp).orderBy("descriptionLastModified","desc").where("detectedLanguage", '==', "en-us").get()
let queryRef = itemsRef.where('descriptionLastModified','<=', oneDayAgoTimestamp).where("detectedLanguage", '==', "en-us").get()
let queryRef = itemsRef.where("detectedLanguage", '==', "en-us").where('descriptionLastModified','<=', oneDayAgoTimestamp).get()
I have made the following composite indexes at the collection level to no avail:
CollectionId:items Fields: descriptionLastModified:DESC detectedLangauge: ASC
CollectionId:items Fields: descriptionLastModified:ASC detectedLangauge: ASC
CollectionId:items Fields: detectedLangauge: ASC descriptionLastModified:DESC
My expectation is I should be able to filter my items by their descriptionLastModified timestamp field and additionally by the value of their detected Language string field.
In case anyone finds this in the future, its 2021, I still find composite indexes created manually, despite being incredibly simple, or you'd think and I fully understand why the OP thought his indexes would work, often just don't. Doubtless there is some subtlety that reading some guides would make clear but I haven't found the trick yet and have been using firestore for over 18 months intensively at work.
The trick is to use the link it creates, but this often fails, you get a dialogue box telling you an index will be created, but no details for you to manually create and the friendly blue 'create' button does nothing, it neither creates the index nor does it dismiss the window.
For a while I had it working in firefox but it stopped. A colleague across a couple of desks who has to create them a lot tells me that Edge is the most reliable, and you have to be very careful to not have multiple google accounts signed in - if edge (or chrome) takes you to the wrong login initially when following the link, even if you switch user back (and you have to do this because it will assume your default login rather than say the one currently selected in your only google cloud console window), even if you switch back its about a 1 in 3. He tells me in edge it works about 60%
I used to get about 30% with firefox just hitting refresh and soon a few times, but cant get it working other than in edge now, and actually, unless there is a client with little cash who will notice, I just go for inefficient and costly queries which return the superset of results and do some filters on the results. Mostly running in nodejs and its nippy enough for my purposes. Real shame to ramp up the read counts and consequential bills, but just doesn't seem a fix.

Is there a way to resolve this error: "CloudKit integration requires does not support ordered relationships."

I'm trying to use Apple's CoreDataCloudkitDemo app. I've only changed the app settings per their README document. On running the demo, I'm getting the error: "CloudKit integration requires does not support ordered relationships."
(The weird grammar in the title is included in the app)
The console log shows:
Fatal error: ###persistentContainer: Failed to load persistent stores:Error Domain=NSCocoaErrorDomain Code=134060 "A Core Data error occurred." UserInfo={NSLocalizedFailureReason=CloudKit integration requires does not support ordered relationships. The following relationships are marked ordered:
Post: attachments
There is the same error for the "Tags" entity.
I'm using Xcode 11.0 beta 4 (11M374r).
I've only changed the bundle identifier, and set my Team Id.
I removed the original entitlements file - no errors in resulting build.
I've not changed any code from the original.
Does anyone have a workaround, or preferably, a fix? Or did I do something wrong?
Thanks
Firstly, select CoreDataCloudKitDemo.xcdatamodeld -> Post -> RelationShips, select attachments relationship, on the Inspect panel, deselect Ordered, then do the same thing on the tags relationship.
Secondly, there will be some errors in the code now, because we unchecked the Ordered option, the property of attachments and tags in the generated NSManagedObject may changed from NSOrderedSet? to NSSet?. So we could change these error lines of code like below:
Origin:
guard let tag = post?.tags?.object(at: indexPath.row) as? Tag else { return cell }
Changed:
guard let tag = post?.tags?.allObjects[indexPath.row] as? Tag else { return cell }
Finally, you can run the code now. ;-)
Further more, on WWDC19 Session 202, the demo shows they set both attachments and tags relationships as Unordered, so I think there's something wrong in the given demo project.

XPages SSJS - Creating a Document in Another Database

I get the error "Exception occurred calling method NotesDatabase.createDocument() null" for the following:
var db:NotesDatabase = session.getDatabase("", viewScope.targetDb);
if (db != null) {
if(db.isOpen()){
}else{
db.open();
}
} else {
}
var doc:NotesDocument = db.createDocument();
Comments:
The database db is available and "open".
The user has enough rights in the targetDb to create documents.
What is wrong?
I changed db.isOpen to db.isOpen(), according to Paul Stephen Withers tips.
And now db.open() gives the error "Exception occurred calling method NotesDatabase.open() null" although that I can get, in viewScope variables, the server, FilePath, etc.
Change
var db:NotesDatabase = session.getDatabase("", viewScope.targetDb);
to
var db:NotesDatabase = session.getDatabase(currentDatabase.getServer(), viewScope.targetDb);
This works on the web as well as XPinC.
XPages isn't the same as formula, it doesn't like the empty string definition for the server name, which is contrary to the documentation which states (for the server parameter of NotesSession.getDatabase - javascript):]
The name of the server on which the database resides. Use null to
indicate the session's environment, for example, the current computer
Using null or "" gives error 500, it would appear.
The code from the question will work, if :
the if block is removed entirely
the viewScope.targetDb variable has a properly specified notes database file path, which exists on the same server as the current database
the current user has access to the target database ( by the ACL ), with the Create Database right
the target database has a Maximum Internet name and password above Reader as per #Paul
I suspect the cause is you're checking db.isOpen. You should check db.isOpen().
Worth bearing in mind is session.getDatabase(String, String) doesn't return null (unless you're using OpenNTF Domino API). It returns a Database object that is not open. So that if statement is irrelevant. Also best practice is to pass a server name to session.getDatabase() - you'll get a different outcome if the application is ever used in XPiNC with your current code.
Regardless of individuals' user access, "Maximum Internet name and password" on the Advanced tab of the ACL will override that. If maximum internet access is No Access, no one will be able to create documents. But I suspect that's not a factor here.
Pro Tip -- Get the Debug Toolbar and use that to print out messages to the XPage debug toolbar to see what is going on and if your viewScope variable is being set. Also, learn to use the try catch block to catch your exceptions and print out the error message to the debug toolbar. You will find your issue that way.
https://www.openntf.org/main.nsf/project.xsp?r=project/XPage%20Debug%20Toolbar

How can I clear an external ID on a record in NetSuite?

I need to clear/reset the external ID on a record in NetSuite, but nothing I do is working.
Some of the InventoryItem records are incorrectly mapped to records in another system. I have an application that can sync up the two systems, but I need to clear NetSuite's external IDs first.
Responses don't really need to be SOAP-specific. If you know how to do it with some specific NetSuite/SuiteTalk client, that might point me in the right direction.
What I've Tried
First up, I tried using the nullFieldList... but maybe it doesn't work because externalId is an attribute, not an element?
<messages:update>
<messages:record internalId="7777" xsi:type="accounting:InventoryItem">
<core:nullFieldList xsi:type="core:NullField">
<core:name>externalId</core:name>
</core:nullFieldList>
</messages:record>
</messages:update>
The external ID is just a string, so I tried just setting it to blank. Didn't work either.
<messages:update>
<messages:record internalId="7777" xsi:type="accounting:InventoryItem">
<accounting:externalId></accounting:externalId>
</messages:record>
</messages:update>
I even tried setting the external ID to 0, but I get back a "not unique identifier" error
<messages:update>
<messages:record internalId="7777" xsi:type="accounting:InventoryItem">
<accounting:externalId>0</accounting:externalId>
</messages:record>
</messages:update>
Other Info
I'm using NetSuite's SOAP API v.2013_1
When I say "it doesn't work", I mean: after I do the update, I get a success response similar to the following:
<readResponse>
<platformCore:status isSuccess="true" xmlns:platformCore="urn:core_2013_1.platform.webservices.netsuite.com"/>
<record internalId="7777" externalId="42" xsi:type="listAcct:InventoryItem" xmlns:listAcct="urn:accounting_2013_1.lists.webservices.netsuite.com">
<!-- snip -->
</record>
</readResponse>
If you are using scripts in netsuite you can run a scheduled script to clear records in NS by loading each record and setting the externalid to '' using the following simple code:
var rec= nlapiLoadRecord(type,id);
rec.setFieldValue('externalid','');
nlapiSubmitRecord(rec);
This seemed to work for me in my enviornment which was on 2015.2.
Unfortunately my understanding is that once you set an externalid you cannot clear it, you can set it to another value, but not back to null. I have experienced this both using SuiteScript as well as a Boomi process that uses the 2014.1 endpoint. This may have changed in the recent releases, as I have not tried it recently with SuiteScript nor with a newer endpoint.
You can eliminate the externalId on a record once it's been set. Here's an example using the NetSuite gem:
ns_customer = NetSuite::Records::Customer.get external_id: 'ext_id'
ns_customer.external_id = ''
ns_customer.update
Here's the corresponding XML for update:
<env:Body>
<platformMsgs:update>
<platformMsgs:record xsi:type="listRel:Customer" platformMsgs:internalId="199113" platformMsgs:externalId=""/>
</platformMsgs:update>
</env:Body>
I have had to attempt this before as well. I know the pains you describe. I ended up putting a "-" in front of my external ID to unlink it between my systems. You can do this in SOAP or even as a simple one time csv upload. As it was one time, I did csv.

Resources