1

I am interested in implementing the following requirements for my e-signature web application.

  1. A user can create a new signing contract. That contract can include multiple users to sign. The contract creator needs to provide emails of the recipients. Every recipient will have additional data assigned, like signing details, instructions and etc.
  2. However, the invited user can still be not present in the system. This is the trickest part.

Right now my following implementation is the following:

  1. I create a contract, then check if a user is present in the system by making a filter by email. If the user exists, I create a many-to-many entity ContractRecipientEvent using intermediate table with additional data, which is assigned to the contract. I create it many-to-many because the same user can be assigned to multiple contracts.
  2. If the user is not present I create the Invitation model, set all recipient's specific data, and send an email. Then the user is registered, I run the query of all Invitations records with that email and create ContractRecipientEvent, by copying data from the Invitation model.

What I don't like with my approach are the following things:

  1. Many-to-many field. I would like to just use plain Foreign keys for my contract recipients, but I am unsure how should I assign multiple users to the same contract? Perhaps I should create a new model ContractRecipient with the user and contract as foreign keys, but that is a many-to-many field also?
  2. I don't like that I need to copy data from the Invitation model to the ContractRecipientEvent and only create ContractRecipientEvent after the user is registered, because I need a user entity to create a ContractRecipientEvent, which has a foreign key to the user.
  3. The permission structure is difficult to manage. I need to check all the users, who are included in the contract database record, and check if they are assigned to the contract id, they are using for the signing POST request.

I am attaching my final JSON code of the contract list. It works, but I would like to have a correct models structure:

{
  "results": [
    {
      "id": 178,
      "is_author": true,
      "title": "ahhzhzh",
      "message_to_all_recipients": null,
      "contract_signing_status": "WAITING_FOR_ME",
      "contract_signing_type": "SIMPLE",
      "contract_signing_date": {
        "start_date": "2010-09-04T14:15:22Z",
        "end_date": "2010-09-04T14:15:22Z"
      },
      "recipients": [
        {
          "message": null,
          "recipient_signing_status": "NOT_SIGNED",
          "recipient_review_status": "NOT_REQUIRED",
          "recipient_action": "SIGN",
          "role": "ADMIN",
          "email": "test2331@gmail.com"
        },
        {
          "message": null,
          "recipient_signing_status": "NOT_SIGNED",
          "recipient_review_status": "NOT_REQUIRED",
          "recipient_action": "SIGN",
          "role": "BASE",
          "email": "test2333@gmail.com"
        }
      ]
    },
    {
      "id": 179,
      "is_author": true,
      "title": "dhhdhd",
      "message_to_all_recipients": null,
      "contract_signing_status": "WAITING_FOR_ME",
      "contract_signing_type": "SIMPLE",
      "contract_signing_date": {
        "start_date": "2010-09-04T14:15:22Z",
        "end_date": "2010-09-04T14:15:22Z"
      },
      "recipients": [
        {
          "message": null,
          "recipient_signing_status": "NOT_SIGNED",
          "recipient_review_status": "NOT_REQUIRED",
          "recipient_action": "SIGN",
          "role": "ADMIN",
          "email": "test123@gmail.com"
        },
        {
          "message": null,
          "recipient_signing_status": "NOT_SIGNED",
          "recipient_review_status": "NOT_REQUIRED",
          "recipient_action": "SIGN",
          "role": "BASE",
          "email": "test233@gmail.com"
        }
      ]
    },
 
  ]
}
New contributor
Viktor Vostrikov is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.
1
  1. Many-to-many field. I would like to just use plain Foreign keys for my contract recipients, but I am unsure how should I assign multiple users to the same contract? Perhaps I should create a new model ContractRecipient with the user and contract as foreign keys, but that is a many-to-many field also?

This many to many relationship is something that actually exists as such in your domain (each contract can have signatures from multiple users and each user can sign multiple documents). You can try to hide it in your model, but most likely you will either constrain your use-cases too much or you will fail in hiding the many-to-many nature of the relationship.

  1. I don't like that I need to copy data from the Invitation model to the ContractRecipientEvent and only create ContractRecipientEvent after the user is registered, because I need a user entity to create a ContractRecipientEvent, which has a foreign key to the user.

You can avoid that copying by having two different states for your User model: Invited and Registered. Then you can create a User instance in the Invited state when you find a non-existing user being added to a document as a signer. This Invited User will most likely not be able to login yet or do any actions that require them to login themselves, but it should be possible for others to refer to them (e.g. add them to additional documents as signer).

Once a user follows the link they received in the invitation email, the User state can be changed to Registered and the details that are provided at registration can be filled in.

This means that the Invitation model only needs to contain details about the invitation itself (which user is being invited, when was the email sent, which link should they follow, etc.)

  1. The permission structure is difficult to manage. I need to check all the users, who are included in the contract database record, and check if they are assigned to the contract id, they are using for the signing POST request.

This is also unavoidable, unless you give each contract/user combination a unique link to add their signature. Then the complexity shifts to the link generation.

7
  • Regarding the two users' states. This is a very good idea! I thought about it myself but could not formulate it the way you did. As far as I understood, the Invitation model could be an OneToOne relationship with a null option. When the user assigns recipients, I would then create an Invitation model. After the recipient registers, I would create a User model and set that OneToOne field to a particular Invitation model. Regarding permissions. Is it alright to just check if recipient is included in contract and if it is, let him do some of the actions:signing, updating or etc? – Viktor Vostrikov 2 days ago
  • As I see it, when a recipient is assigned who doesn't have a corresponding User model, you create both a User and an Invitation model. After that recipient registers, you can delete the Invitation model (it has served its purpose and is no longer needed). The Invitation model would have a mandatory OneToOne relationship to User, but the other direction would be optional. – Bart van Ingen Schenau 2 days ago
  • Regarding the permissions, I can't really tell if that will work. It depends on the requirements you have about who can do which actions. – Bart van Ingen Schenau 2 days ago
  • Ok, one more question. Suppose that two contract owners decide to invite the same user, with the same email? So, by following this approach I should create a user with an invited state, that would include the only email. Create an Invitation model and assign it to the User. However, what should I do if another person invites this same user? I can't create another User model, because the User technically is created, he just did not register. I think about changing OneToOne to Foreign keys, then it will be easier to track. – Viktor Vostrikov yesterday
  • The user has been invited already, so no new invitation is needed. You might consider sending an email to all users that are added to a contract to notify them they are supposed to sign something. In your case, what would happen if a user responds to both invitations and tries to register multiple times? – Bart van Ingen Schenau yesterday

Your Answer

Viktor Vostrikov is a new contributor. Be nice, and check out our Code of Conduct.

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.