Does somebody know if it is possible to change one of documents in a series of recurring meetings?
I changed one of them with c# api and it changed all documents in the series (e.g. 5 docs in series will be modified during one save() call)
var document = view.GetFirstDocument();
if (document != null)
{
do
{
var item = document.GetFirstItem("Repeats");
var repeat = tmpItem != null ? Convert.ToInt32(tmpItem.Text) : 0;
if(repeats)
{
document.ReplaceItemValue("myVal", "1"); //it change all my 5 docs after first save
document.Save(true, false);
}
document = view.GetNextDocument(document);
}
while (document != null);
}
From "Lotus Notes Calendar and Scheduling explained! Part 1":
the instance document of a repeating meeting can be split into multiple documents if the chair reschedules some instances. Consider a repeating meeting that repeats once a week for five weeks. If the chair advances the first and second instance by an hour, the single response document for all five instances is now split into two response documents: one for the first and the second instance and another for the remaining instances.
And from the "IBM Lotus Notes and Domino Calendaring & Scheduling Schema":
Repeating events are scheduled more than once over time and are represented by at least two notes in a parent-child relationship. The parent note is identified by its ApptUNID item (which is its note universal ID), and the child note is identified by the same ApptUNID as the parent and the original RepeatInstanceDates. The ApptUNID and RepeatInstanceDates items form a key pair of values that uniquely identify a particular repeat instance. More details are covered in the Repeat Model section of this paper.
So what you basically have to do is find the child Document of the event ($CSFlags conatins "i" and $Ref the parents UNID) and create a new (second) child document for the changed date/time, removing this particular date/time entry from the existing child document, IIRC.
In such cases, I always do that manually in the Notes Client and then compare the fields created that way with the ones I created via my code.
In the code you loop through the view and change all documents that are available in the view. You need to pick the document you want to change.
EDIT:
A repeating entry is a document shown multiple times in a view. So it is possible that you are updating the same document multiple times. Compare the UniversalID of all the documents in the series to be sure.
If you change one of the entries using the Lotus Client it will ask if you want to update all, if you select "just this instance" the entry will be saved in a new document. So a repeating entry can be a single document or a combination of documents.
The best advice, and really the only advice, that I can give you is to study the LotusScript code in the mail template, and see exactly what it does when a user changes one entry in a repeating appointment. Lotus has not documented it in any other way, but the template code is all open source and it is the ultimate authority. Your task is to be compatible with what they do in the template -- otherwise it is pretty likely that your code will have side-effects that cause problems for users who try to use the Notes client to take additional actions on the calendar event series after your code has run.
Related
The general process
Documents are uploaded to DocuSign creating a new Envelope.
Templates are applied to this Envelope.
Recipients are updated to make sure there is no mixup with signers from the template
The Envelope is sent to the signers.
Intended use of templates
The primary use of templates is to allow users to upload documents and use all other information from templates like fields and other setting for the uploaded documents. Signers can also be freely set and overwrite the ones defined in the template.
For applying templates we use https://developers.docusign.com/docs/esign-rest-api/reference/envelopes/envelopetemplates/applytodocument/
The Template
The template consist of 2 documents. The first document has 3 pages and the second document has 2 pages.
There is one signer. A signature box is added to the last page of both documents.
The Problem
Test scenario: The exact same documents as in the template. This results in the signature box on the second document is not set.
Test scenario: Use the 3 page file for both documents. This results in the signature box being put on page 3 of both documents. So it looks like the assignment works only from document 1 to all the other documents
Test scenario: Use different 3 page documents that match the template for both documents. The result is the same as in the 2. test scenario.
What I tried
The described scenarios are based on this (simplyfied) code for applying the templates:
//variables envAPI (class EnvelopesApi), accountId, templateId and envelope (class Envelope) are already set
DocumentTemplateList templateList = new DocumentTemplateList();
templateList.DocumentTemplates = new List<DocumentTemplate>();
templateList.DocumentTemplates.Add(new DocumentTemplate()
{
TemplateId = templateId,
DocumentId = "1"
});
envAPI.ApplyTemplateToDocument(accountId, envelope.EnvelopeId, "1", templateList);
templateList = new DocumentTemplateList();
templateList.DocumentTemplates = new List<DocumentTemplate>();
templateList.DocumentTemplates.Add(new DocumentTemplate()
{
TemplateId = templateId,
DocumentId = "2"
});
envAPI.ApplyTemplateToDocument(accountId, envelope.EnvelopeId, "2", templateList);
//some recipient checking is done here
envAPI.Update(accountId, envelope.EnvelopeId, envelope);
I also tried using more entries in templateList.DocumentTemplates but that only caused INVALID_REQUEST_BODY errors.
I realized the DocumentID property of the documents in the templates are very different after the first file. My test template has 1 for the first document and the ID of the second document is a very large number. Using this large number also causes INVALID_REQUEST_BODY errors.
Is this actually correct and the error is somewhere else? Because it looks like it should work this way. Or is the problem located somewhere else?
The workflow that you are trying is a perfect place to use a composite template. The recommendation is use one composite template per document. In one POST envelopes call you can swap out the documents on the templates with documents at runtime and apply server (saved) templates to the documents. You can add recipients, drop recipients by not including them, and also add tabs or write values to tabs at runtime. See:
https://www.docusign.com/blog/dsdev-from-the-trenches-composite-templates
https://www.docusign.com/blog/dsdev-why-use-composite-templates
To answer my own question: This doesn't work. At least not this way.
Yes, composite templates are one way of dealing with this requirement but then again, why do multi-document templates even exist?
So the answer is quite simple: Do it the other way around.
To use a multi-document template properly, the template needs to be the starting point. Use a template and replace the files to create an evenlope instead of creating an envelope first and then applying templates to the envelope.
I have a c# web api hosted in iis which has a post method that takes a list of document ids to insert into a lotus notes database.
The post method can be called multiple times and I want to prevent insertion of duplicate documents.
This is the code(in a static class) that is called from the post:
lock (thisLock)
{
var id = "some unique id";
doc = vw.GetDocumentByKey(id, false);
if (doc == null)
{
NotesDocument docNew = db.CreateDocument();
//some more processing
docNew.Save(true, false, false);
}
}
Even with the lock in place, I am running into scenarios where duplicate documents are inserted. Is it because a request can be execute on a new process? What is the best way to prevent it from happening?
Your problem is: getdocumentbykey depends on the view index being up to date. On a busy server there is no guarantee that this is true. You can TRY to call a vw.Update, but unfortunately this does not trigger an update of the view index, so it might be without any effect (it just updates the vw object to represent what has changed in the backend, if the backend did not update, then it does nothing).
You could use db.Search('IdField ="' & id & '"', Nothing, 0) instead, as the search does not rely on an index to be rebuilt. This will be slightly slower, but should be way more accurate.
you might want to store the inserted ids in some singleton object or even simply static list. And lock on this list - whoever obtains the lock verifies that the ids it wants to insert are not present and then adds them to the list itself.
You need to keep them only for a short length of time, just so that 2 concurrent posts with the same content does not update plus normal view index gets updated. So rather store timestamp along id, so you can clean out older records if the list grows long.
I've got a MS Word project where I'm building a number of Panes for users to complete some info which automatically populates text at bookmarks throughout the document. I'm just trying to find the best way of saving these values somehow that I can retrieve them easily when re-opening the document after users have typed in their values.
I could just try to retrieve them from the bookmarks themselves but of course in many cases they contain text values when I'd ideally want to store a primary key somewhere that's not visible to the user and just in case they made changes to the text which would make reverse engineering the values impossible.
I can't seem to find any information on saving custom attributes in a Word document, so would really appreciate some general guidance of how this might be achieved.
Thanks a lot!
I would suggest the use of custom document properties. there you can strings in a key -value manner (at least if it is similar to excel).
I found a thread which explains how to do it:
Set custom document properties with Word interop
After playing around with this a fair bit this is my final code in case it helps someone else, I've found this format easier to understand and work with. It's all based on the referenced article by Christian:
using Office = Microsoft.Office.Core;
using Word = Microsoft.Office.Interop.Word;
using System.Reflection;
Office.DocumentProperties properties = (Office.DocumentProperties)Globals.ThisDocument.CustomDocumentProperties;
//Check if the property exists already
if (properties.Cast<Office.DocumentProperty>().Where(c => c.Name == "nameofproperty").Count() == 0)
{
//Then add the property and value
properties.Add("nameofproperty", false, Office.MsoDocProperties.msoPropertyTypeString, "yourvalue");
}
else
{
//else just update the value
properties["nameofproperty"].Value = "yourvalue";
}
In terms of retrieving the value it's as easy as using the same three lines at the top to get the properties object, perhaps using the code in the if statement to check if it exists, and the retrieving it using properties["nameofproperty"].Value
I've a simple client registration system that runs over a network. The system is supposed to generate a unique three digit ID (primary key) with the current year concatenated (e.g. 001-2013). However, I've encountered the problem that the same primary keys being generated when two users from different computers (over a LAN) try to register different clients.
What if the user cancels the registration after an ID is already generated? I've to reuse that ID for another client. I've read about static variable but it didn't solve my problem. I really appreciate your ideas.
Unique and sequential IDs are hard to implement. To completely achive it you would have to serialize commiting creation of client information so ID generated only when data is actually stored, otherwise you'll endup with holes when something wrong happened during submittion.
If you don't need strict sequential numbers - giving out ranges of ID (1-22, 23-44,...) to each system is common approach. Instead of ranges you can give out lists of IDs to use ({1,3,233,234}, {235,236,237}) if you need to use as many IDs as possible.
Issue:
New item -001 is created, but not saved yet
New item -002 is created, but not saved yet
Item -001 is cancelled
What to do with ID -001?
The easiest solution is to simply not assign an ID until an item is definitely stored.
An alternative is, when finally saving an item, you look up the first free ID. If the item from step 2 (#2) is saved before the one from step 1, #2 gets ID -001. When #1 then gets saved, the saving logic sees that its claimed ID (-001) is in use, so it'll assign -002. So ID's get reassigned.
Finally you can simply find the next free ID when creating a new item. In the three steps described above, this'll mean you initially have a gap where -001 is supposed to be. If you now create a new item, your code will see -001 is unused and will assign that to the new item.
But, and that totally depends on your requirements which you didn't specify, now -001 was created later in time than -002, I do not know if that is allowed. Furthermore at any given moment you can have a gap in your numbering where an item has been cancelled. If it happens at the end of a reporting period, this will cause errors (-033, -034, -036).
You also might want to include an auto-incrementing primary key instead of this invoice number or whatever it is.
I've got a bit of a weird situation in MS CRM 4.0.
The quote form contains extra, custom elements which contain the calculated value with taxes already added; these are not handled by the CRM automatically, and since the laws over here can be tricky, it's best to leave this up to the user to pick the tax rate on various items.
Needless to say, my plugins have to calculate this total amount on their own. I've managed to do this using pre plugins when creating and updating quote detail elements; a child step is registered on pre quote update, which calculates the proper amount using a shared variable (passed on from the parent context of either pre update or pre create quote detail elements).
However, things get strange when I try to do the same with the delete message on a quote detail. First a pre delete message step is fired, as expected. In this step, I created the shared variable which contains the calculated total value of each quote detail that is not deleted. Then I expected a pre update step on quote to be fired, with the parent context being the delete step quote detail... it is not so: instead, the parent context is a quote retrieve step.
As such, I am unable to calculate the total tax value, as I cannot use the shared variable (different contexts). I also cannot use the retrieve step, as within it I won't have the information about which quote detail will in fact be deleted (at this point it hasn't been deleted yet).
This retrieve step was a rather unpleasant surprise. Is it normal? If so, what can I do to pass a shared variable from the quote detail delete step?
While this particular case of delete step is indeed handled differently in the CRM using the retrieve step, the problem I had was not clearing the cache in my plugin, therefore getting the quote details along with the one that was deleted.