Code autogeneration by backend
Introduction
In scope of modular implementation in Nepal support for claim code autogeneration was added. This article will describe the way it works and will provide tips to implement this feature in other modules if needed.
Backend - changes to core module and signals
Firstly, let’s describe few changes that had to be made to the general core module and its component for the whole mechanism to work. First of all, code handling mutation was changed in a following way:
# TODO this code is necessary for autogenerate functionality to work
# TODO General mutation code should be reworked
if mutation_data.get('autogenerate', False) and isinstance(messages, Dict):
data.update(messages)
error_messages = None
else:
error_messages = messages
Thanks to this we can use result of mutation to change logs afterwards - code handling creation of claim is generating claim code, but this is not available during creation of the log, so this workaround was needed.
Notice that ‘autogenerate’ is needed (to exist and to be equal to True) as an argument in any mutation that will use this mechanism. This name is generic, so it can be used in any module without problems.
Thanks to this data when we are creating claim we can add following code:
def on_claim_after_mutation(sender, **kwargs):
if kwargs.get('error_messages', None):
return []
elif kwargs.get('mutation_class', None) != 'CreateClaimMutation':
return []
if 'data' in kwargs and kwargs['data'].get('autogenerate'):
try:
mutation_client_id = kwargs.get('data')['client_mutation_id']
mutation_log = MutationLog.objects.filter(client_mutation_id=mutation_client_id).first()
mutation_log.client_mutation_label = kwargs['data']['client_mutation_label']
mutation_log.autogenerated_code = kwargs['data']['code']
mutation_log.save()
return []
except KeyError as e:
logger.error("Client Mutation ID not found in claim signal after mutation, error: ", e)
return []
def bind_signals():
signal_mutation_module_validate["claim"].connect(on_claim_mutation)
signal_mutation_module_after_mutating["claim"].connect(on_claim_after_mutation)
This binds signal to mutation and successful creation of new claim entity. After claim is generated, this code is run to check if there are no errors, if this mutation is really a CreateClaimMutation (we do not want to change code when updating) and if given claim was created through autogeneration mechanism.
If those conditions are met, we fetch relevant mutation log and change two values:
mutation_log.client_mutation_label = kwargs['data']['client_mutation_label']
mutation_log.autogenerated_code = kwargs['data']['code']
First one changes log value in the Journal, instead of “Create Claim - auto” we will receive there “Create Claim - your_code”. Second one is used for frontend to change code value in the form after it is created.
autogenerated_code has been added to MutationLog model in core module, so it can handle autogenerated values for different mutations.
Backend - changes specific to claim module
changes log value in the Journal, instead of “Create Claim - auto” we will receive there “Create Claim - your_code”. Second one is used for frontend to change code value in the form after it is created.
autogenerated_code has been added to MutationLog model in core module, so it can handle autogenerated values for different mutations.
The following settings have been added to the claim module settings:
autogenerated_claim_code_config
has been defined as dictionary, so if any other implementation of code autogeneration needs custom settings they can be easily provided, without changing structure of claim module config.autogenerate_func
describes which function should be used to autogenerate code - in this case it points to the nepali implementation. Other method would have to be assigned here if it were to replace nepali one.
First important change to the mutation code itself is adding a decorator:
This ensures that one claim will begin to be created only after previous one had been finished. Without this collision are possible, since autogenerate_func
could return the same value for two concurrent processes.
Remaining code is straightforward:
If autogenerate_code
was sent by frontend as is set to True - replace code by the one autogenerated by backend. Notice that this means that value “code” is merely a placeholder in that example - frontend could send anything and it will not be used. This was decided as an easier solution than conditional sending of code value.
Whole nepali code autogeneration on backend can be found here.
Frontend - relevant changes
Autogeneration of codes is much simpler from the frontend side - additional variable is sent, code field is set to readonly and query has to be run to retrieve code value after successful mutation.
In this PR(and later fix), we send two variables to the backend:
As mentioned Placeholder does not matter much, and it should work with any value picked by the user. Although it is recommended to stay with “auto” for debugging purposes. If isAutogenerateEnabled setting is on, frontend will replace code value with placeholder and send True as value of autogenerate. Additionally code field is set to read-only and “auto” is set as a code of a claim.
Apart from that, it is possible to display this autogenerated code instantly after form saving. The entire process will be illustrated using the claim entity as an example.
First and foremost, we need to change the "save" function to be asynchronous.
After saving the entity, we must retrieve the generated code. This can be achieved using a mutation and mutationClientId, which will allow us to fetch the automatically generated code and replace it in the form. As a result, after saving, the field will be updated.
The final step will be disabling the code validation, which can be done by using shouldValidate util function.
Did you encounter a problem or do you have a suggestion?
Please contact our Service Desk
This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License. https://creativecommons.org/licenses/by-sa/4.0/