I have a need to be able to update a large number of memorized transactions, namely sales orders. So, the transactions are generated, but there may or may not be certain fields that need to be updated each time they are generated. A coworker of mine tried a mass update, and I tried doing some scripted updates, and we both were greeted with the same error: MEMORIZED_TRANS_ERROR - Attempting to access memorized transaction as a non-memorized transaction. Is there a way to accomplish such a mass edit/update and avoid this error?
Would help if you showed some code but a guess is you are using the wrong record type. It should be memdoc. The help topic Memorized Transaction Definition has example code.
Sample Code
Memorized transaction definitions can only be created in the NetSuite user interface. The example script below first loads an existing memorized transaction definition with ID 2. Then, it sets the Action field to “Reminder”, and sets the Next Transaction Date in the Custom Dates subtab to 12/12/2020. It saves this date, and then saves the memorized transaction definition.
var r = nlapiLoadRecord('memdoc', 2)
r.setFieldValue('action', 'REMINDER')
r.selectNewLineItem('customdates')
r.setCurrentLineItemValue('customdates', 'nextdate', '12/12/2020')
r.commitLineItem('customdates')
var id = nlapiSubmitRecord(r);
Related
I'm looking to update a list of orders (and statuses) real-time on a webpage. The orders in the (MySQL) database are updated asynchronously through other processes (PHP).
I'm familiar with the mechanics of pushing data to pages (polling, event-source). This is not about that.
What I'm struggling with is figuring out exactly what data to push for each user without
needlessly updating list entities that don't need to be
not missing an update.
My table does have a DateTime column last_update_date that I update when there are any changes to the order. I know MySQL doesn't really have any event triggers that can trigger other code.
Ideas so far:
In my JS I could track the time of the last request and on every subsequent request, ask for data since that time. This doesn't work because JS time will most likely not match server MySQL time.
The same could probably done storing the server time in the user session. I feel like this would probably work most of the time, but depending on the timing of the DB update and the requests, changes could be missed since the DB only stores a DateTime with a precision of 1 second.
I'm sure there's a more atomic way to do this, I am just drawing a blank though. What are suitable design patterns for this?
You are correct that you must poll your database for changes, and that MySQL can't push changes to other applications.
The trick is to use server time throughout for your polling. Use a table to keep track of polling. For example, suppose your users have user_id values. Then make a poll table consisting of
user_id INT primary key
polldate DATETIME
Then, when you poll do this sequence.
First make sure your user has an entry in the poll table showing a long-ago polldate. (INSERT IGNORE doesn't overwrite any existing row in the table.)
SET #userid := <<your user's id>>;
INSERT IGNORE INTO poll (user_id, polldate) VALUES (#userid, '1970-01-01')
Then when you poll, do this sequence of operations.
Lock the poll row for the user:
BEGIN TRANSACTION;
SELECT polldate INTO #polldate
FROM poll
WHERE user_id = #userid
FOR UPDATE;
Retrieve the updated rows you need; those since the last update.
SELECT t.whatever, t.whatelse
FROM transaction_table t
JOIN poll p ON t.user_id = p.user_id
WHERE user_id = #userid
AND t.last_update_date > p.polldate;
Update the poll table's polldate column
UPDATE poll p
SET p.polldate = IFNULL(MAX(t.last_update_date), p.polldate)
FROM transaction_table t
JOIN poll_p ON t.user_id = p.user_id
WHERE user_id = #userid
AND t.last_update_date > p.polldate;
And commit the transaction.
COMMIT;
Every time you use this sequence you'll get the items from your transaction table that have been updated since the preceding poll. If there are no items, the polldate won't change. And, it's all in server time.
You need the transaction in case some other client updates a transaction table row between your SELECT and your UPDATE queries.
The solution O.Jones provided would work for making tracking updates atomic, though where it fails is if the following scenario occurs all within one second:
An order update is written to the table (update 1)
A poll action occurs
An order update is written to the table (update 2)
In this scenario, the next poll action will either miss update 2, or will duplicate update 1, depending on if you use > or >= in your query. This is not the fault of the code, it's a limitation of the MySql datetime type having only 1 second resolution. This could be somewhat mitigated with MySql v8 as it has Fractional Seconds Support though this still would not guarantee atomicity.
The solution I ended up using was creating a order_changelog table
CREATE TABLE 'NewTable' (
'id' int NULL AUTO_INCREMENT ,
'order_id' int NULL ,
'update_date' datetime NULL ,
PRIMARY KEY ('id')
);
This table is updated any time a change to an order is made essentially numerating every update.
For the client side, the server stores the last ID from order_changelog that was sent in the session. Every time the client polls, I get all rows from order_changelog that have an ID greater than the ID stored in the session and join the orders to it.
$last_id = $_SESSION['last_update_id'];
$sql = "SELECT o.*, c.id as update_id
FROM order_changelog c
LEFT JOIN orders o ON c.order_id = o.id
WHERE c.id > $last_id
GROUP BY o.id
ORDER BY order_date";
I now am guaranteed to have all the orders since last poll, with no duplicates, and I don't have to track individual clients.
I have one class Messages with 3 principal fields:
id FromUser ToUser
I do have a query where the To = Value field and the From field is not repeated. I mean, get all FROMUSER who sent me a message.
Any Idea?
Thanks!
As #Fosco says, "group by" or "select distinct" are not supported yet in Parse.com.
Moreover keep in mind the restriction on the selection limit (max 1000 results for query) and timeout request call ( 3 seconds in the before save events, 7/10 seconds in the custom functions ). For the "count" selection, the restriction is the timeout request call.
I'm working on Parse.com too, and i've changed a lot the structure of my db model, often adding some inconsistent columns in several classes, keeping them carefully updated for each necessary query.
For cases like yours, i suggest to make a custom function, that keep in input two parameter ( we can say, "myLimit" and "myOffset" ) for the lazy loading, then select the slices, and programmatically try to filter the resulting array item list (with a simple search using for..loop, or using some utility of UnderscoreJS). Start with small slices ( eg: 200-300 records maximum for selection ) until the last selection returns zero results ( end reached). You could count all items before start all of this, but the timeout limitation could cause you problems. If this not works as expected try to make the same, client side.
You could also make a different approach, so creating another table/class, and for each new message, adding the FromUser in that table ONLY if it doesn't already exist, for that specified ToUser.
Hope it helps
I have an entity called product. There is a field called item price.
Now i have created 100 products. I want to SUM (mathematical operation) all the products "item price" field and display it in an other entity called opportunity field called "total items price".
Besides this if i create 101 product and it's "item price", "total items price" field in opportunity automatically up date itself.
So for i have SUMMED to fields of a form. e.g there is a field A and field B, multiplying field A with 3.14 and displaying result in field B.
Here is the Code.
function SumField() {
var price = Xrm.Page.getAttribute("new_price");
var total_price = Xrm.Page.getAttribute("new_total_price");
if(price.getValue() != null) {
var newValue = price.getValue() * 3.14;
total_price.setValue(newValue);
// Make sure the changes are saved back to the server - in CRM 4.0, this was crmForm.new_fieldname.ForceSubmit = true;
Xrm.Page.getAttribute("new_total_price").setSubmitMode("always");
}
}
JavaScript will not work in this scenario, atleast it will not be the most optimum solution.
Rather than handling it with JavaScript write a Plugin that fires on change in Product entity and updates the desired record of opportunity entity. (I am considering that there will be few products related to one opportunity i.e. 1:N relationship)
In case you want that change in one product will update values in all records Opportunity create a another entity say "Configuration" which will hold this value and show it on Opportunity form using JavaScript (reason being: If one product record creation updates all records of Opportunities it will impact performance of CRM)
You have some possibilities, the best choice depends of your technology expertise:
Workflow - launch workflow when the field new_total_price changed and update the opportunity related. For this you don't need any known of programming languages
Plugin - in update of your product entity you can update the related opportunity. You need know C# or VB .NET
Javascript - One solution is onload of opportunity you check if product related has (you case use FetchXML or OData for example) the new_total_price filled, with that information you can update your opportunity.
There is more alternatives but you have here some options.
Is there any documentation about how Revision.Description is populated and under what condition?
I'm writing a Custom Application for Rally so that I can view changes made to Task and HierarchicalRequirement objects via a table with a rolling 7 day period.
The attributes that I'm interested in are:
HierarchicalRequirement
PlanEstimate
TaskEstimateTotal
TaskActualTotal
TaskRemainingTotal
Task
Estimate
ToDo
Actuals
I'm traversing Revisions to get snapshot views of tasks and stories:
It's easy to retrieve these attributes for the current day. However, I need to traverse RevisionHistory -> Revisions and then parse the Revision.Description to apply the differences for Task and HierarchicalRequirement objects. This may provide a daily snapshot of each object.
For example: the following were appended to Revision.Description after took place:
TASK REMAINING TOTAL changed from [7.0] to [4.0]
TASK ESTIMATE TOTAL changed from [7.0] to [4.0]
The "rolling 7 day" period is just an example. My intention is to create a table with a breakdown of Team -> Story -> Task -> Estimate -> ToDo along the y-axis and Iteration -> daily-date along the x-axis.
Tim.
The Revision.description field on many of the Rally object types was not originally intended for developers to get change information but rather for display purposes for our Rally ALM SaaS tool - that's why changes are put in a Revision attribute called 'description' which is just a text field. So there is no developer documentation on the format of this data since it is a text field and not intended to be parsed and the format could change in the future (in the future there will be a better way to get object change information. More on this later in this post...)
However, there is a pattern in this data. It is:
ATTRIBUTE_NAME action VALUE_CLAUSE
The actions are 'added' or 'changed'.
The value clause format is based on the action type. For the 'added' action the value clause is [value]. For the 'changed' action the value clause is 'from [old value] to [new value]'.
For example, for an existing User Story that had an owner set to 'Newt' from 'No Entry', a new revision instance is created the description would have this contained in it:
OWNER added [Newt]
If then later the user changed the owner to 'John', then a new revision will be created that looks like this:
OWNER changed from [Newt] to [John]
If there is more than one attribute change then the changes are separated by commas and there is no guaranteed sorting order of the changes.
Now for the better way to do this in the future. Since you are not the only developer that wants to get at object changes we have a new product under development that will have WSAPI endpoints exposed where you can get changes for an object in a programatic way that should avoid you needing to parse data. But since this product is under development you'll have to do what you are doing now and hopefully my explanation of the format of the data in the description will help you in the meantime.
Hope this helps.
The data you are seeking may also exist in the IterationCumulativeFlowData or ReleaseCumulativeFlowData objects in Rally's WSAPI:
https://rally1.rallydev.com/slm/doc/webservice/
That should be easier (and perform better) than grepping through all the revision history entries.
Salesforce allows you to extend Object definitions by using Record Types. Is there a quick and easy way to allow users to transition groups of Objects from one Record Type to another? In my case, I will be keeping track of students as they progress through the undergraduate student life cycle from applicant to alumnus. It makes sense to me to keep track of the different phases of the student life cycle as Record Types so that I can create custom interfaces/viewing permissions/business logic for each phase. I was hoping to be able to create a custom button or link to do this as per this example from Salesforce:
Salesforce: Getting Started With Buttons and Links.
However I have had no luck querying the RecordType object using the Ajax toolkit to find out which RecordTypeId I will need to update the Object to. (I am rather new to JavaScript so it may simply be my inexperience that's getting in the way. I would be happy to post code samples of what I've tried so far if anyone asks.)
On the IdeaExchange someone mentioned that you can just include the RecordType field in the object's custom layout page (IdeaExchange: Provide a Means of Changing Record Types), but this does not seem like a reasonable solution for managing hundreds of students.
Using a workflow or a trigger does not seem like a reasonable solution either because those apparently require you to update a record or create a new one. Students should be able to transition at any time, independently of updates or new additions.
SO likes it when you mention other things that your issue could pertain to, but I think those areas are pretty self-explanatory here; this issue is relevant any time you might like to programatically transition between different record types.
What you want is probably not the RecordType object itself, but rather the RecordTypeId field on your object you are using to track students which looks up to that RecordType object. For example, to find the record type of a given student, the SOQL would look like:
SELECT RecordTypeId FROM Student__c WHERE Id = {some id}
and then if you wanted to update the record, you could change the value of the RecordTypeId like this:
var student = new sforce.SObject("Student__c");
student.Id = '{some id}';
student.RecordTypeId = '{new record type id}';
result = sforce.connection.update([student]);
To find the eligible RecordTypeIds for a given object type, you can either query the RecordType object and filter on the SObjectType column, or just call describeSObject(Student__c) and inspect the RecordTypeInfos node in the result.