docassemble
docassemble copied to clipboard
Usage of question keyword <sets>
HI,
Looking at the examples, it seems that a variable specified with sets is only used like an "anchor" for a question, and not a real variable. For example: `
question: | this is my question 1 fields:
- How old are you?: var_age sets: myquestion1_ok
question: | this is my question 2 fields:
- What's your name?: var_name sets: myquestion2_ok
` after executing the first step, trying to debug, I'm expecting to see a variable myquestion1_ok set to True in /vars, but I find only var_age set by the user input
Could you clarify the usage? Thanks
Yes, sets
only applies to the block as a whole. (It is used on code
blocks as well as question
blocks.) It cannot be used on specific fields.
All that sets
does is advertise that a block may define a variable; whether the block actually defines the variable depends on what the block does. Usually you don't need to use sets
, because docassemble can figure out what variables are set by a block. For example, it scans the syntax of a code
block, looking for the use of the assignment operator =
, and figures out the variables that might be set based on what is on the left hand side of the operator.
You might want to look at the continue button field
feature if you want to set a true/false variable after the user clicks Continue on a particular field. https://docassemble.org/docs/fields.html#continue%20button%20field
Thanks for the clarify. The problem is that a button field can be used only with questions that use fields. I loose the yesno questions, signature, review questions and so on...
I've the following workflow in a multiuser environment. A technician starts an interview and fills some data, then he makes a sign. at this point, a mail is sent to the project manager and the technician must wait for the review and sign of the project manager. When the project manager receives the notification he sign in. He must review the questions, makes a sign and then a pdf is produced with the data of the interview and the two signs. I wouldn't like use roles, if possible.
The problem is that I feel hard (maybe I'm missing something) to "force" a desired workflow. I use the initial code block (that runs when every question is rendered) to check the user that has logged in. I need a way to know if the user has just started or restarted the interview (maybe another user has already completed some questions, but he has just started or restarted the interview), and I don't know how to determine this in the initial block. Actually, code block "auto discovery and fill" of variables present in other questions is very powerfull but sometimes makes difficult to keep the desired workflow. Is there a way to debug how the tracker choose a question or a code block (like the callstack printed when there is an error)?
- It could be very usefull have a property of a code block, like:
autofill: false
in this case, docassemble should not search for question or other code blocks to fill the variables. This should help write mandatory code that is not "influenced" by other questions (it's all demanded to the developer)
- the sets operator could have two options:
sets:
- bookmark: mybookmarkid
sets:
- variable: myvariable_ok
the bookmark could do the same things that currently does, and the variable could set a real boolean value
To explain better my doubts, below an example (simplified):
When the second user (project manager) logs in, technician_user attributes are overwritten with second user information (Michael Rabbit) Does it mean that the mandatory code block is whole re-executed? technician_user wasn't already gathered?
The same for the above code. If I put:
if not email_sent_project_manager_ok:
insted of:
if not defined('email_sent_project_manager_ok'):
the email is sent multiple times.
In the signature question I must use a variable. If I use directly project_manager_user.signature I receive an error.
question: |
${ project_manager_user }, please sign the document
signature: project_manager_user_signature
under: |
${ project_manager_user }
mandatory: True
Interview:
metadata:
title: Plant Testing
---
modules:
- .common
---
objects:
- technician_user: Individual
- technician_user.signature: DAFile
- project_manager_user: Individual
- project_manager_user.signature: DAFile
---
id: event email interested people
event: send_mail_to_interested_people
code: |
email_sent_project_manager_ok = send_email(to=project_manager_user, template=notification_project_manager)
wait_other_users
---
initial: true
code: |
if not user_logged_in():
kick_out_user
---
id: main
code: |
multi_user = True
technician_user = Individual()
technician_user.name.first = user_info().first_name
technician_user.name.last = user_info().last_name
technician_user.email = user_info().email
technician_user.gathered = True
project_manager_user = Individual()
project_manager_user.name.first = 'Michael'
project_manager_user.name.last = 'Rabbit'
project_manager_user.email = '[email protected]'
user_filled_data
technician_user.signature = technician_user_signature
if not defined('email_sent_project_manager_ok'):
send_mail_to_interested_people
else:
if not email_sent_project_manager_ok:
send_mail_to_interested_people
user_reviewed_data
project_manager_user.signature = project_manager_user_signature
user_confirms_document
mandatory: True
---
id: step ask date
question: |
When have you done the work?
fields:
- Date: data_doc_date
datatype: date
required: True
- subject: data_subject
required: True
continue button field: user_filled_data
mandatory: True
---
id: step ask sign technician
question: |
${ technician_user }, please sign the document
signature: technician_user_signature
under: |
${ technician_user }
mandatory: True
---
id: step project manager review data
field: user_reviewed_data
question: |
${ technician_user },
${ data_doc_date } ${ data_doc_date }
subquestion: |
now you'll be asked to sign the document
mandatory: True
---
id: step ask sign project manager
question: |
${ project_manager_user }, please sign the document
signature: project_manager_user_signature
under: |
${ project_manager_user }
mandatory: True
---
id: step ask confirm document
question: |
${ project_manager_user }
${ project_manager_user.signature }
Confirm?
yesno: user_confirms_document
mandatory: True
---
code: |
if user_confirms_document:
info_sent = True
else:
info_sent = False
---
id: step thanks
mandatory: True
need:
- info_sent
question: |
% if info_sent:
Thanks
% else:
Interview cancelled
% endif
subquestion: |
% if info_sent:
The interview is finished
% else:
Interview cancelled
% endif
buttons:
Restart: restart
---
id: event kick_out_user
event: kick_out_user
question: |
Sorry, but you need to login
buttons:
- Log in: signin
- Exit: exit
---
id: event wait for other users
event: wait_other_users
question: |
Please ask ${ project_manager_user } to sign following this
[link](${ interview_url(temporary=0) })
After that ${ project_manager_user } has signed,
come back
(using
[the same link](${ interview_url(temporary=0) }))
Press **Check** to verify if you can continue.
buttons:
- Verify: refresh
---
id: template notification project manager
template: notification_project_manager
subject: |
Need Help
content: |
Hi, ${ project_manager_user },
${ technician_user } needs your help
Fly at this [link](${ interview_url(temporary=0) })
Good job!
---
I hope I explained myself correctly. Thanks!
See https://docassemble.org/docs/logic.html#howitworks
Every time the screen loads, the system will go through the YAML file and run every mandatory
block that has not already been run to completion. So if you have a mandatory
block that requires asking question
s, that mandatory
block will be run multiple times. There is no reason to repeatedly re-run the code that defines multi_user
or technician_user.name.first
. So you should put that preliminary code into its own mandatory
code block. Then that code block will run to completion when the interview first starts, and it will be marked as completed, so it will not be run again.
id: main1
mandatory: True
code: |
multi_user = True
technician_user = Individual()
technician_user.name.first = user_info().first_name
technician_user.name.last = user_info().last_name
technician_user.email = user_info().email
project_manager_user = Individual()
project_manager_user.name.first = 'Michael'
project_manager_user.name.last = 'Rabbit'
project_manager_user.email = '[email protected]'
---
id: main2
mandatory: True
code: |
user_filled_data
technician_user.signature
if task_not_yet_performed('email_sent_project_manager'):
send_mail_to_interested_people
user_reviewed_data
project_manager_user.signature
user_confirms_document
The best way to let the second user review the information that the first user added is to use a review
screen. https://docassemble.org/docs/fields.html#review
Alternatively, you could do something like this:
mandatory: True
code: |
favorite_fruit
favorite_vegetable
favorite_fungus
---
mandatory: True
question: |
Now, let's review.
field: review_intro
---
mandatory: True
code: |
if task_not_yet_performed('review'):
mark_task_as_performed('review')
force_ask('favorite_fruit', 'favorite_vegetable', 'favorite_fungus')
final_screen
The force_ask()
function will create a list of screens that need to be shown. The system will remember this list and make the user go through the list. But the function should only be called once, or else you'll get into an infinite loop.