Question Status

Verified
DavidR asked a question on 10 Nov 2013 8:37 PM

Hi,

  I'm testing out some electronic signatures.  I've got the signature system to prompt correctly when a field in a form is updated but when I update() or insert() a field directly into a table via x++ nothing seems to happen.  From the formdatasource the stack indicated that the singature code runs form the super() call in the validatewrite on the datasource.

 Does anyone know what methods or actions need to be taken via x++ to trigger the electronic signature?

Thanks

Reply
André Arnaud de Calavon responded on 11 Nov 2013 5:44 AM

Hi David,

When changing the field itself, the electronic signature is not triggered. It is triggered when a write action to the database is called. (insert, update or delete).

Normally the electronic signature will be triggered then automatically. It is possible to use a x++ statement to disable the call of this logic per table. I can't recall the method, but think it was the table.skipDatabaseLog() method.

Did you use a statement like table.skip...[something]?

Also another question: did you use a build in signature or a custom on a table?

kind regards,

André Arnaud de Calavon  |  Microsoft Dynamics AX Solution architect  |  My blog  |  My company

This post is my own opinion and does not necessarily reflect the opinion or view of my company, Microsoft, both its employees, or other MVPs.

Reply
Verified Answer
Justin Biggs responded on 11 Nov 2013 6:42 AM

Hi David,

In addition to André's suggestion, I would also add that the validateWrite() method isn't called automatically when you're updating a record from X++.  You could add something like this to your code:

 

if (record.validateWrite())

{

record.write();

}

That should trigger the super() call in validateWrite() for you.

Reply
Suggested Answer
André Arnaud de Calavon responded on 11 Nov 2013 11:21 AM

Hi David,

I have checked the code used to disable the Signature when writing from x++ to the database. It is indeed the SkipDatabaseLog method.

kind regards,

André Arnaud de Calavon  |  Microsoft Dynamics AX Solution architect  |  My blog  |  My company

This post is my own opinion and does not necessarily reflect the opinion or view of my company, Microsoft, both its employees, or other MVPs.

Reply
DavidR responded on 11 Nov 2013 2:30 PM

Hi André,

  Thanks for your response.   I'm not using any 'skip' type statements.  Its a custom table with a container field that I'm updating.  I've got a custom signature requirement setup on this field.  The code is simply

       .....

       ttsBegin;

       reportTable.selectForUpdate(true);

       reportTable.update();

       ttsCommit;

       ......

I also tried doupdate() without any luck.  Perhaps I need to setup some table properties?  I'll compare against a table which is working for signatures.

Cheers

David

Reply
DavidR responded on 11 Nov 2013 3:32 PM

I'm also getting "Transaction does not contain a required signature" error...

Reply
DavidR responded on 11 Nov 2013 9:42 PM

Thanks Justin,

  That makes sense.  I've tried calling the validatewrite().  Even though it is running this command it doesn't seem to be getting to the signature code.

Regards

David

Reply
DavidR responded on 11 Nov 2013 10:27 PM

I think I may need to make a call to info.collectESignature(...

I'm fried for today but I'll test it out tomorrow.

Reply
Verified Answer
André Arnaud de Calavon responded on 12 Nov 2013 12:14 AM

Hi David,

I think I overlooked something in your question. I had a similar issue about a year ago. It is very hard to understand how and where to call the signature from x++ code manually. Also if you have the signature, how to store everything so AX thinks it is signed correctly.

When you are using a form datasource, the signature will be prompted. If you are using a variable to fill/modifty a table it will not be called, but you then get the error "Transaction does not contain a required signature".

We solved it by using a form datasource and interact with this one. This prevented us for deeply looking into this signature framework.

kind regards,

André Arnaud de Calavon  |  Microsoft Dynamics AX Solution architect  |  My blog  |  My company

This post is my own opinion and does not necessarily reflect the opinion or view of my company, Microsoft, both its employees, or other MVPs.

Reply
Verified Answer
DavidR responded on 12 Nov 2013 9:03 PM

Thanks André,

  I've played with this today and used the formdatasource to update the table.  This got me to the signature process but I hit a bug in /classes/SIGBaseDocument.value2str() line 47 (“wrong argument type for function”).  I think it can’t understand how to interpret the pdf object in the container.  I can comment this line out and it all works but given this is deep down leaving this commented out is bad news.

 Anyway,  this is actually one of the problems I was running into in my original table update method so I think I did actually get it to work outside of the form data source.  So for anyone looking at this in the future (and not working with a pdf in a container) I think this would work for you:

    When you want to write your change to the table (in this case called reportTable)...

           if (reportTable.validatewrite())

           {    

               reportTable.selectForUpdate(true);

               ttsBegin;

               reportTable.update();

               ttsCommit;

           }  

  The validate write method...

           public boolean validateWrite()

           {

               boolean     ret;

               Info        info  = new info();

               ret = super();

               ret = info.collectESignature(DatabaseLogType::Update, this);

               return ret;

           }

You'd want to have a condition in there to determine the correct databaselogtype (update or insert) to sent to the collectESignature() method but this would be straight forward.  If the bug wasn't there I think this would work fairly well.

Thanks Justin for contributing to this answer too.

DR

Reply
André Arnaud de Calavon responded on 13 Nov 2013 1:10 AM

Hi David,

Thanks for sharing your findings.

kind regards,

André Arnaud de Calavon  |  Microsoft Dynamics AX Solution architect  |  My blog  |  My company

This post is my own opinion and does not necessarily reflect the opinion or view of my company, Microsoft, both its employees, or other MVPs.

Reply
DavidR responded on 13 Nov 2013 7:08 PM

Just finishing this off,  I did a bit more testing today and confirmed (at least well enough for now) that it is the file in the container that causes the run time issue with the strfmt.  Putting a string or int in the container causes no issues and signs the change happily.  This bit of code may not be that critical to the process of signing but I'm not really game to play around with code down at this level to avoid the bug - particularly for legal / compliance related functions (see bottom of msdn.microsoft.com/.../cc589558.aspx)

Perhaps this is a bug which is fixed in a newer release.  Moving onto something else now.

Reply
DavidR responded on 13 Nov 2013 9:45 PM

..and finally this was interesting

community.dynamics.com/.../159471.aspx

Reply
Vincent Nguyen responded on 10 Sep 2014 2:21 AM

Hi All,

I'm facing same error message "Transaction does not contain a required signature" when cheque status is updated to paid while generating AP payment.

I tried to call info.collectESignature() in validateWrite method but I'm getting another error "Cannot create a signature: already in a transaction (level 2)."

In standard, we cannot save the record until electronic signature is completed.

Might have to change standard code so my ttslevel is 0 before calling validateWrite() and info.collectESignature()

Reply
Verified Answer
Justin Biggs responded on 11 Nov 2013 6:42 AM

Hi David,

In addition to André's suggestion, I would also add that the validateWrite() method isn't called automatically when you're updating a record from X++.  You could add something like this to your code:

 

if (record.validateWrite())

{

record.write();

}

That should trigger the super() call in validateWrite() for you.

Reply
Verified Answer
André Arnaud de Calavon responded on 12 Nov 2013 12:14 AM

Hi David,

I think I overlooked something in your question. I had a similar issue about a year ago. It is very hard to understand how and where to call the signature from x++ code manually. Also if you have the signature, how to store everything so AX thinks it is signed correctly.

When you are using a form datasource, the signature will be prompted. If you are using a variable to fill/modifty a table it will not be called, but you then get the error "Transaction does not contain a required signature".

We solved it by using a form datasource and interact with this one. This prevented us for deeply looking into this signature framework.

kind regards,

André Arnaud de Calavon  |  Microsoft Dynamics AX Solution architect  |  My blog  |  My company

This post is my own opinion and does not necessarily reflect the opinion or view of my company, Microsoft, both its employees, or other MVPs.

Reply
Verified Answer
DavidR responded on 12 Nov 2013 9:03 PM

Thanks André,

  I've played with this today and used the formdatasource to update the table.  This got me to the signature process but I hit a bug in /classes/SIGBaseDocument.value2str() line 47 (“wrong argument type for function”).  I think it can’t understand how to interpret the pdf object in the container.  I can comment this line out and it all works but given this is deep down leaving this commented out is bad news.

 Anyway,  this is actually one of the problems I was running into in my original table update method so I think I did actually get it to work outside of the form data source.  So for anyone looking at this in the future (and not working with a pdf in a container) I think this would work for you:

    When you want to write your change to the table (in this case called reportTable)...

           if (reportTable.validatewrite())

           {    

               reportTable.selectForUpdate(true);

               ttsBegin;

               reportTable.update();

               ttsCommit;

           }  

  The validate write method...

           public boolean validateWrite()

           {

               boolean     ret;

               Info        info  = new info();

               ret = super();

               ret = info.collectESignature(DatabaseLogType::Update, this);

               return ret;

           }

You'd want to have a condition in there to determine the correct databaselogtype (update or insert) to sent to the collectESignature() method but this would be straight forward.  If the bug wasn't there I think this would work fairly well.

Thanks Justin for contributing to this answer too.

DR

Reply
Suggested Answer
André Arnaud de Calavon responded on 11 Nov 2013 11:21 AM

Hi David,

I have checked the code used to disable the Signature when writing from x++ to the database. It is indeed the SkipDatabaseLog method.

kind regards,

André Arnaud de Calavon  |  Microsoft Dynamics AX Solution architect  |  My blog  |  My company

This post is my own opinion and does not necessarily reflect the opinion or view of my company, Microsoft, both its employees, or other MVPs.

Reply