handling merge scenario in user event script in netsuite - merge

I have successfully handled 'create', 'delete' and 'edit' types in afterSubmit event in a User Event script in NetSuite. What I need now is a way to capture Merge events. When I merge two customer records in Netsuite, the function below isn't invoked at all while it's invoked when I create, delete or edit a customer:
function afterSubmit(type)
{
...
}
Is there any way to handle merge scenarios?

Merge is not an event, it is handled by a duplicate manager.
Unless you hijack the merge button from the client side, I'm not sure it can be done.

Based on #felipechang's advice, I created a custom Merge Suitelet and all of the logic needed to go with it. All code can be found here
Step 1
Create (or add logic to) the Customer User Event script to hide the existing merge button and add a separate one.
gist
Step 2
Create (or add logic to) the Cutomer Client script to wire up the merge button click event.
gist
Step 3
Create a Merge page Suitelet that mimics the functionality of the out-of-the-box merge page but behaves differently on submit.
gist
Step 4
Create a Merge page Client script
gist
Step 5
Create a scheduled task that gets launched on Merge submit to check the progress of the merge task and then fire off custom logic if it succeeds
gist
Hopefully that saves someone some time.

An alternative solution to editing netsuite standard scripts, is to run a scheduled mapReduce on the netsuite record type in question. Running a search in the mapReduces getInputData, filtering on ["systemnotes.context","anyof","DPL"] (DPL => Duplicate Resolution) and processing the affected records in the map. Depending how immediately you need the event of the merge dictates the regularity of the scheduling. Unfortunately you cannot get the data of the merging record. If this is needed, I would recommend the business process is put in place to add the desired data to the master record before doing a merge.

Related

Smartsheet-api, Is there any way to get manually deleted row using smartsheet api or sdk call

I am deleting row from a sheet, On a sheet I have daily job which needs to recognize the deleted records, I need a way to recognize them using smartsheet api or sdk..
Thanks in advance..
I don't believe this scenario (identifying deleted rows) is explicitly supported by the API at this time. Seems like you could still use the API to achieve your goal though, with a bit more work (code) on your part.
Your code would have to get the sheet data (i.e., all sheet rows) at a regular interval and save that data somewhere -- then each time job runs, get the sheet data again and compare that data to the data you saved the previous time the job ran (to identify any rows that had been deleted).
Edit 9/26: Added Webhooks info
Note that with the approach I've described above, any rows that had been added AND deleted during the interval between job runs would not be detected. If it's important to identify each and every time a row is deleted, a better (and much more efficient) approach would be to use Webhooks. By using webhooks, your application subscribes to notifications for a specified sheet, and then would receive a callback (HTTP POST) from Smartsheet any time the sheet changes. Your application would need to inspect the information in each callback it receives to identify 'deleted row' events (eventType = deleted and objectType = row).
A simple way to do this is to add a column with a checkmark named "delete" or something similar, then with automation you can move the row to another sheet when the flag is detected, the row will be removed from the original sheet, but you will have a record of the deleted row in a different sheet that you can read or do what ever you need to do, this will also prevent deletions by mistake and you can even restore the row back if you need to. I don't think you need much code to implement this solution.

DDD: How to solve this using Domain-Driven design?

I'm new to DDD and cutting my teeth on the following exercise. The use case is real, but my attempt to solve it with DDD is purely for learning.
We have multiple Git repos, each containing a file that we call
product spec. The system needs to respond to a HTTP POST by cloning all
the repos, and then update the product spec in those that match some
information in the POST body. System also needs to log the POST request as the cause for updating the product spec.
I'd like to use Aggregates and event sourcing for solving this problem because they seem like a good fit. Event sourcing comes with automatic persistence of the commands, so if I convert the POST body to a command, I get auditing for free.
Problem is, the POST may match multiple product spec. I'm not sure how to deal with that. Should I create a domain service, let it find all the matching product spec and then issue an update command to each? Or should I have the aggregate root do so? If using aggregate root to update multiple entities, it itself needs to be an entity, so what would it be in my problem domain?
The first comment to your question is right (the one of #VoiceOfUnreason): this 'is mostly side effect coordination'.
But I will try to answer your question: How to solve this using DDD / Event Sourcing:
The first aggregate root could just be named: 'MultipleRepoOperations'. This aggregate root has only one stream of events.
The command that fires the whole process could be: 'CloneAndUpdateProdSpecRepos' which carries a list of all the repos to be cloned and updated.
When the aggregate root processes the command it will simply spit a bunch of events of type 'UserRequestedToCloneAndUpdateProdSpec'
The second bounded context manages all the repos, and it its subscribed to all the events from 'MultipleRepoOperations' and will receive each event emitted by it. This bounded context aggregate root can be called: 'GitRepoManagement', and has a stream per repo. Eg: GitRepoManagement-Repo1, GitRepoManagement-Repo215, GitRepoManagement-20158, etc.
'GitRepoManagement' receives each event of type 'UserRequestedToCloneAndUpdateProdSpec', replays its corresponding repo stream in order to rehydrate the current state, and then tries to clone and update the product spec for the repo. When fails emits a failed event or a suceed if appropiate.
for learning purposes try to choose problem domain that has more complex rules and logic, where many actions is needed. for example small game (card game,multiplayer quiz game or whatever). or simulate some real world process like school management or some business process.

Call external web service from within Crm 2016

I have some functionality I need to implement in Dynamics Crm 2016. I need to scan all records for a custom entity and update any record where a certain condition is true. This is a bit too complex to do via a workflow (I can't change owner via a workflow step) so I'm thinking perhaps I could perform this logic in a custom plugin. I don't know if it makes sense to call this plugin from a workflow in crm though, as I need to perform the logic on all records for this particular entity, and I need the logic to run regularly, i.e. daily/weekly. What's the best way to do this?
I figured this out. It was actually possible to do entirely within Crm. What I was trying to do was the following.
I have a custom entity called announcement, and it has a custom field called embargo date.
I needed to somehow check periodically if the embargo date has been reached, meaning, is the embargo date today? If so, then I needed to change the owner of this entity.
If the embargo date has not yet been reached, then I need to wait until it is, checking the date again everyday till it is reached.
I managed this with a workflow. I added my check conditions, if they were true I assigned the entity to another user.
If my conditions weren't true, I added wait step to wait for 1 day,then another step to Start workflow where I called the current workflow recursively. Meaning, if the conditions aren't true have the workflow call itself again.

building audit trail functionality

Following is a use case in a workflow system
Work order enters into a system. Work order will have a target which goes through different workflow states before completing a work order.
Say Work order for a target Vehicle came into a system - workflow for this work oder involves 2 tasks say
a)wash vehicle
b)inspect vehicle
Say wash vehicle workflow task changes vehicle attribute from "not washed" to "washed". And say "inspect vehicle" workflow task changes vehicle attribute "not inspected" to "inspection done"
If user is pulling work order data user will always see latest vehicle data (in this example assuming both workflow tasks are completed user will see value "washed" and "inspection done". However when user pulls ONLY workflow Task Wash Vehicle data -> user will see "washed" -Though second task was done, workflow Task 1 will only see that that it modified. Getting data for Workflow Task 2 will see both "washed" and "inspection done"
This involves milstoning (audit trail) of data; One approach is as shown below image - where when workflow task modifies data it'll update version number, modified_ts and maintain that version number in it's own data row (via a JOIN table as depicted below). Basically this is nothing but maintaining a reference to a history record for workflow task data so when pulling workflow task data it knows which history record to pull back. please ignore parent_id and other notes, noise in a below picture. it's not relevant for this question.
I am thinking event sourcing will also be another alternative design - however don't want to apply event sourcing(or any other similar solution) as a whole sale solution but only for this particular use case (affecting only 3 or so tables where audit trail matters). I am trying to evaluate if CQRS/Event sourcing is a right fit as a partial solution (again only limited to 3-4 tables which need to preserve history/audit trail data) or ES/CQRS will be an overkill? any other thoughts?
P.S. Though this isn't related to Scala - Scala is a platform we are using hence tagging it to see if there are language specific solutions that can help. tagging Akka for finding out if ES/CQRS via Akka persistence is an option or not. Postgresql is a db - And DB triggers is not a solution I am looking for.

Detect when a record is being cloned in trigger

Is there a way to detect that a record being inserted is the result of a clone operation in a trigger?
As part of a managed package, I'd like to clear out some of the custom fields when Opportunity and OpportunityLineItem records are cloned.
Or is a trigger not the correct place to prevent certain fields being cloned?
I had considered creating dedicated code to invoke sObject.Clone() and excluding the fields that aren't required. This doesn't seem like an ideal solution for a managed package as it would also exclude any other custom fields on Opportunity.
In the Winter '16 release, Apex has two new methods that let you detect if a record is being cloned and from what source record id. You can use this in your triggers.
isClone() - Returns true if an entity is cloned from something, even if the entity hasn’t been saved.
getCloneSourceId() - Returns the ID of the entity from which an object was cloned.
https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_methods_system_sobject.htm#apex_System_SObject_getCloneSourceId
https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_methods_system_sobject.htm#apex_System_SObject_getCloneSourceId
One approach, albeit kind of kludgy, would be to create a new field, say original_id__c, which gets populated by a workflow (or trigger, depending on your preference for the order of execution) when blank with the salesforce id of the record. For new records this field will match the standard salesforce id, for cloned records they won't. There are a number of variations on when and how and what to populate the field with, but the key is to give yourself your own hook to differentiate new and cloned records.
If you're only looking to control the experience for the end user (as opposed to a developer extending your managed package) you can override the standard clone button with a custom page that clears the values for a subset of fields using url hacking. There are some caveats, namely that the field is editable and visible on the page layout for the user who clicked the clone button. As of this writing I don't believe you can package standard button overrides, but the list of what's possible changes with ever release.
You cannot detect clone operation inside the trigger. It is treated as "Insert" operation.
You can still use dedicated code to invoke sObject.Clone() and exclude the fields that aren't required. You can ensure that you include all fields by using the sObject describe information to get hold of all fields for that object, and then exclude the fields that are not required.
Hope this makes sense!
Anup