Get TaskID for Case Activities - acumatica

I was getting TaskID for Case Activities (Screen ID - SP203010) using Acumatica Web API. Now after upgrading it to version 6.0, I am not getting that. I have also tried different properties available but seems nothing is getting me that TaskID.
I am storing these activities into my database pulling from Acumatica Partner Portal and to avoid duplicate activities being imported, I was comparing it with TaskID.
Below is the code snippet I am using to get TaskID
SP203010WS.Screen context = new SP203010WS.Screen();
context.CookieContainer = new System.Net.CookieContainer();
context.AllowAutoRedirect = true;
context.EnableDecompression = true;
context.Timeout = 1000000;
context.Url = "https://sso.acumatica.com/Soap/SP203010.asmx";
PartnerPortalCreds loginCreds = GetCreds();
string username = loginCreds.PARTPRTUSE;
string password = loginCreds.PARTPRTPAS;
SP203010WS.LoginResult result = context.Login(username, password);
SP203010WS.Content content = context.GetSchema();
context.Clear();
string[][] export = context.Export
(
new SP203010WS.Command[]
{
new SP203010WS.Value
{
Value = currentAcumaticaCaseNo,
LinkedCommand = content.Case.CaseID
},
content.Activities.Type,
content.Activities.Summary,
new SP203010WS.Field { FieldName="Body", ObjectName="Activities"},
content.Activities.StartDate,
content.Activities.CreatedBy,
new SP203010WS.Field { FieldName="TaskID", ObjectName="Activities"},
},
null,
0, true, true
);
Let me know whether it has been moved or deprecated in newer version. What shall I be using instead of TaskID or where can I find that TaskID.

In Acumatica 6.0 table EPActivity was splitted on CRActivity, SMEmail and PMTimeActivity. Original table was renamed to Obsolete_EPActivity.
Now NoteID is the key field on all tables. SMEmail and PMTimeActivity contains RefNoteID field - foreign key from CRActivity.
You may find value pair TaskID and NoteID in table - Obsolete_EPActivity

#Krunal, as Ken mentioned, after upgrade to 6.0 value pair TaskID and NoteID is only available in the Obsolete_EPActivity table. One should use Obsolete_EPActivity table to replace obsolete TaskID integer values with actual NoteID GUIDs.
There is no way to access Obsolete_EPActivity table through Web Services. After upgrade to 6.0, Acumatica inserts new Activities only in the CRActivity table.
To avoid duplicate activities, you have to store actual NoteID GUIDs in your database instead of obsolete TaskID integer values and compare GUIDs while importing records.
For previously imported activities you will also have to replace TaskID values with actual NoteID GUIDs. Searching for CRActivity record based on CaseID, Subject and CreatedDateTime field values stored in your DB, you should find appropriate record and use its NoteID to replace legacy TaskID value.

Related

Get SharePoint item from document library based on custom metadata

I am storing metadata with my documents and folders in SharePoint. This metadata includes an itemid which is a unique identifier from the system it came from. Is there a way to retrieve the item from SharePoint using Graph API by specifying the itemid in the metadata?
This query works for properties that Microsoft provides like name:
https://graph.microsoft.com/v1.0/sites/{siteid}/drive/root/children?$filter=name eq 'Z'
But if I try it with the custom property then I simply get an empty result:
https://graph.microsoft.com/v1.0/sites/{siteid}/drive/root/children?$filter=itemid eq 'Z'
Is there a way to query documents and folders with custom properties like this?
Here is the code used to update the field on the document in SharePoint using Graph API:
public FieldValueSet UpdateListItem(string siteId, string driveId, string fileItemId, Dictionary<string, object> additionalData)
{
var updateFileTagsRequest = graphClient.Sites[siteId].Drives[driveId].Items[fileItemId].ListItem.Fields.Request();
var fieldValueSet = new FieldValueSet { AdditionalData = additionalData };
var result = updateFileTagsRequest.UpdateAsync(fieldValueSet).Result;
return result;
}
The dictionary values being passed to the UpdateListItem method are strings and look like this: "ItemId", "A unique value"

Azure Cosmos DB - Update existing documents with an additional field

Existing Cosmos DB documents need to be altered/updated with a new property & also existing documents of other collections need to be updated with the same new property along with its value.
Is there any recommended way or tool available to update existing documents on Cosmos DB, or is writing the custom c# application/PowerShell script using Cosmos DB SDK is the only option?
Example:
Existing user document
{
id:user1#mail.com,
name: "abc",
country: "xyz"
}
Updated user document
{
id:user1#mail.com,
name: "abc",
country: "xyz",
guid:"4334fdfsfewr" //new field
}
Existing order document of the user
{
id:user1#mail.com,
user: "user1#mail.com",
date: "09/28/2020",
amt: "$45"
}
Updated order document of the user
{
id:user1#mail.com,
user: "user1#mail.com",
userid: "4334fdfsfewr", // new field but with same value as in user model
date: "09/28/2020",
amt: "$45"
}
I'd probably go with:
Update user documents through a script
Have Azure Function with Cosmosdb trigger that would listen to changes on users documents and update orders appropriately
[UPDATE]
whatever type of script you feel best with: PS, C#, Azure Functions...
now, what do you mean they need to be altered with the new property "on the same time"? i'm not sure that's possible in any way. if you want such an effect then i guess your best bet is:
create new collection/container for users
have an Azure Function that listens to a change feed for your existing users container (so, with StartFromBeginning option)
update your documents to have new field and store them in a newly created container
once done, switch your application to use new container
its your choice how would you change other collections (orders): using changeFeed & Azure Functions from old or new users container.
PS.
Yes, whatever flow i'd go with, it would still be Azure Functions with Cosmos DB trigger.
I have added some solution for .Net Core API 3.0 or higher version.
// You can put any filter for result
var result = _containers.GetItemLinqQueryable<MessageNoteModel>().Where(d => d.id == Id
&& d.work_id.ToLower() == workId.ToLower()).ToFeedIterator();
if (result.HasMoreResults)
{
var existingDocuments = result.ReadNextAsync().Result?.ToList();
existingDocuments.ForEach(document =>
{
//Creating the partition key of the document
var partitionKey = new PartitionKey(document?.work_id);
document.IsConversation = true;
//Inserting/Updating the message in to cosmos db collection: Name
_containers.Twistle.ReplaceItemAsync(document, document.document_id, partitionKey);
});
}
We had the same issue of updating the Cosmos DB schema for existing documents. We were able to achieve this through a custom JsonSerializer.
We created CosmosJsonDotNetSerializer inspired from Cosmos DB SDK. CosmosJsonDotNetSerializer exposes the FromStream method that allows us to deal with raw JSON. You can update the FromStream method to update document schema to your latest version. Here is the pseudo-code:
public override T FromStream<T>(Stream stream)
{
using (stream)
{
if (typeof(Stream).IsAssignableFrom(typeof(T)))
{
return (T)(object)stream;
}
using (var sr = new StreamReader(stream))
{
using (var jsonTextReader = new JsonTextReader(sr))
{
var jsonSerializer = GetSerializer();
return UpdateSchemaVersion<T>(jsonSerializer.Deserialize<JObject>(jsonTextReader));
}
}
}
}
private T UpdateSchemaVersonToCurrent<T>(JObject jObject)
{
// Add logic to update JOjbect to the latest version. For e.g.
jObject["guid"] = Guid.NewGuid().ToString();
return jObject.ToObject<T>();
}
You can set Serializer to CosmosJsonDotNetSerializer in CosmosClientOptions while creating CosmosClient.
var cosmosClient = new CosmosClient("<cosmosDBConnectionString>",
new CosmosClientOptions
{
Serializer = new CosmosJsonDotNetSerializer()
};
This way, you always deal with the latest Cosmos document throughout the code, and when you save the entity back to Cosmos, it is persisted with the latest schema version.
You can take this further by running schema migration as a separate process, for example, inside an Azure function, where you load old documents, convert them to the latest version and then save it back to Cosmos.
I also wrote a post on Cosmos document schema update that explains this in detail.

AutoMapper - Retrieve a different field from a linked source table than the one that links it

I have the following table structure that mixes legacy fields with an updated schema:
Coaster
Id (Int)
ParkId (Int)
Park
Id (int)
UniqueId (Guid)
So, the Coaster and Park tables are linked using the Park.Id field. The UniqueId field is not currently used in the old schema. We are migrating to a clean DB using AutoMapper, and this new schema looks like this:
Coaster
Id (Int)
ParkId (Guid)
Park
Id (Guid)
The problem I am having is doing this using AutoMapper. I've been experimenting with this code:
private ModelMapper()
{
Mapper.Initialize(x =>
{
x.AddProfile<ConvertersMappingProfile>();
});
}
// This is the part that I'm trying to work out
public ConvertersMappingProfile()
{
CreateMap<Park, NewSchema.Park>()
.ForMember(dst => dst.Id, map => map.MapFrom(src => src.ParkId));
}
In the new schema, the Park table's Id matches the old schema's UniqueId.
My question is: Because in the old schema there is no direct link to the UniqueId value of the Park table, how to do I get that value to map to the new schema using the Coaster.ParkId field to Park.Id field mapping?
I used a custom resolve to fix the problem. So I created my resolver, which pulls up a list of the items in the database (which is typically pretty small) to get all the values from the table I need, and retrieves the value. (Pre-refactored code):
public class ParkResolver : IValueResolver<Original.Park, New.Park, string> {
public string Resolve(Original.Park source, New.Park dest, string destMember, ResolutionContext context) {
List<Original.Park> list = new List<Original.Park>();
using (IDbConnection con = new SQLiteConnection(#"Data Source=C:\Users\Me\Documents\Parks.sql;")) {
con.Open();
list = con.Query<Original.Park>($"SELECT * FROM Parks WHERE Id = {source.ParkId}").ToList();
con.Close();
}
return list.FirstOrDefault().UniqueId;
}
}
And I call my custom resolver for the tables I am mapping:
CreateMap<Original.Park, New.Park>()
.ForMember(dst => dst.ParkId, map => map.MapFrom(new ParkResolver()));
Hopefully that will help someone else.

Azure Search not returning document ID

Im using azure search. I have my id field set as retrievable yet its not getting returned in my search results. Do you guys know why? I only see: document object -> key value, in the search result of an individual document. (Im using the .net SDK)
I want this ID to do a document lookup and serve the real document to the consumer.
public static DocumentSearchResult GetSearchResult(ISearchIndexClient indexClient, string searchTerm)
{
SearchParameters parameters;
DocumentSearchResult results;
parameters =
new SearchParameters()
{
Select = new[] { "content" }
};
results = indexClient.Documents.Search(searchTerm, parameters);
return results;
}
I found out that i could put ID in searchparameters to retrieve it. This feels unnatural though..
I found out that i could put ID in searchparameters to retrieve it.
parameters =
new SearchParameters()
{
Select = new[] { "content", "id" }
};
As a side note: to serve the document to the caller you need to add the metadata_storage_path to the index (and to the searchparameters to retrieve it as a searchresult)!
https://learn.microsoft.com/en-us/azure/search/search-howto-indexing-azure-blob-storage

querying the System Notes in Netsuite

I have been looking for a way to pull the records in the System Notes in NetSuite. The lines below throw an 'INVALID_RCRD_TYPE' error:
var columns = new Array();
columns[0] = new nlobjSearchColumn('internalid').setSort();
var results = nlapiSearchRecord('systemnote', null, null, columns);
I wonder how to reference the System Notes as the first argument of nlapiSearchRecord API. Obviously, it's not called systemnote.
A similar question has been posted here but the System Notes has been incorrectly referenced there.
systemnotes aren't available as record type which is evident from the record browser link
However, you can still get system notes fields using join searches on any record type in NetSuite
eg:
x = nlapiSearchRecord('vendor', null, null,
[new nlobjSearchColumn('date', 'systemNotes'),
new nlobjSearchColumn('name', 'systemNotes'), // Set By
new nlobjSearchColumn('context', 'systemNotes'),
new nlobjSearchColumn('newvalue', 'systemNotes'),
new nlobjSearchColumn('oldvalue', 'systemNotes'),
])
x[0].getValue('name', 'systemNotes'); //gives the set by value
Thanks for your responses guys. I finally managed to query the System Notes using the code below. I thought I should share it in case someone else wants to accomplish the same job. I created a RESTlet in NetSuite using the below code that returns the list of merged customer records merged after a given date.
I created a new search with ID customsearch_mergedrecords and in Criteria tab, added a filter on 'System Notes: NewValue' where the description is 'starts with Merged with duplicates:' and in the Results tab, I added the columns I needed.
Note that you need to create the new search on Customer, not on System Notes. System Notes is hooked up in the search using join (the second argument in nlobjSearchFilter constructor).
function GetMergedRecordsAfter(input) {
var systemNotesSearch = nlapiLoadSearch('customer', 'customsearch_mergedrecords');
var filters = new Array();
filters.push(new nlobjSearchFilter('date', 'systemNotes', 'notbefore', input.fromdate));
systemNotesSearch.addFilters(filters);
var resultSet = systemNotesSearch.runSearch();
var searchResultJson = [];
resultSet.forEachResult(function (searchResult){
var searchColumns = resultSet.getColumns();
searchResultJson.push({
ID: searchResult.getValue(searchColumns[0]),
Name: searchResult.getValue(searchColumns[1]),
Context: searchResult.getValue(searchColumns[2]),
Date: searchResult.getValue(searchColumns[3]),
Field: searchResult.getValue(searchColumns[4]),
NewValue: searchResult.getValue(searchColumns[5]),
OldValue: searchResult.getValue(searchColumns[6]),
Record: searchResult.getValue(searchColumns[7]),
Setby: searchResult.getValue(searchColumns[8]),
Type: searchResult.getValue(searchColumns[9]),
InternalId: searchResult.getValue(searchColumns[10])
});
return true;
});
return searchResultJson;
}

Resources