Electronic Signatures

This question is answered

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

Verified Answer
  • 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.

  • 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.

  • 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

All Replies
  • 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.

  • 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.

  • 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.

  • 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

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

  • 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

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

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

  • 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.

  • 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

  • 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.

  • 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.

  • ..and finally this was interesting

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