-
-
Notifications
You must be signed in to change notification settings - Fork 221
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Case Import Payment Validation #35803
base: master
Are you sure you want to change the base?
Conversation
corehq/apps/case_importer/views.py
Outdated
return render_error( | ||
request, | ||
domain, | ||
_('The Excel file is missing one or more required fields for the "{}" case type: {}'.format( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very nit: The error message as is was a little surprising to me when it listed out the missing case types since the message didn't sound like it will do that.
How about changing the text to something below (in my mind it reads a little better)?
The Excel file is missing the following required fields for the "{}" case type: {}
(it is very nit, so feel free to ignore if you want, but I thought I'd mention in nonetheless)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Your suggestion does make the text feel a little more streamlined and easier to read. Happy to update this.
Addressed in 926eb08.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Additionally, I think the correct way to use the translation would be
_('The Excel file ... "{}" case type: {}').format()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Addressed translation formatting in 9da1701.
corehq/toggles/__init__.py
Outdated
@@ -3010,3 +3010,10 @@ def domain_has_privilege_from_toggle(privilege_slug, domain): | |||
tag=TAG_SOLUTIONS, | |||
namespaces=[NAMESPACE_DOMAIN], | |||
) | |||
|
|||
MOBILE_WORKER_VERIFICATION = StaticToggle( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: if this is only for MTN I'd suggest renaming this to MTN_MOBILE_WORKER_VERIFICATION
OR MTN_USER_VERIFICATION
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed in d1d68f2.
corehq/apps/case_importer/views.py
Outdated
@@ -377,6 +379,16 @@ def excel_fields(request, domain): | |||
|
|||
case_field_specs = [field_spec.to_json() for field_spec in field_specs] | |||
|
|||
if MOBILE_WORKER_VERIFICATION.enabled(domain) and case_type == MOMO_PAYMENT_CASE_TYPE: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to worry about bulk import?
Seeing at the function documentation
case_type:
For a bulk import, this will be displayed
as the special value for bulk case import/export, and the fetching of
the case types will be handled in the next step
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should accommodate bulk imports too, as noted by this Jira comment.
It is true that a bulk import will have a special case type and so this check will fail, however we handle validation for bulk imports separately within the _create_bulk_configs()
function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so this check will fail
and so the columns wont be verified for a bulk import here but they are verified in _create_bulk_configs
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is correct. The config for a bulk import only gets created in excel_commit()
and that is where _create_bulk_configs()
is called which will then validate for a bulk import.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does that catch missing columns as well or just checks for values that should not be set?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The check in _create_bulk_configs()
will only validate that all the required headers are included. When checking for the values themselves, this will happen in the same place as a single case type import within do_import.py::_validate_payment_fields()
corehq/apps/case_importer/views.py
Outdated
@@ -377,6 +379,16 @@ def excel_fields(request, domain): | |||
|
|||
case_field_specs = [field_spec.to_json() for field_spec in field_specs] | |||
|
|||
if MOBILE_WORKER_VERIFICATION.enabled(domain) and case_type == MOMO_PAYMENT_CASE_TYPE: | |||
missing_fields = _check_payment_fields_exist(columns) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: since the function is return missing fields, I'd suggest renaming the function to _get_missing_payment_fields
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed in 523002f.
corehq/apps/case_importer/views.py
Outdated
return render_error( | ||
request, | ||
domain, | ||
_('The Excel file is missing one or more required fields for the "{}" case type: {}'.format( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Additionally, I think the correct way to use the translation would be
_('The Excel file ... "{}" case type: {}').format()
corehq/apps/case_importer/views.py
Outdated
|
||
|
||
def _check_payment_fields_exist(columns): | ||
return [ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would it be better to use sets here to find the missing fields?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mean by doing something as follows?
return set(MOMO_REQUIRED_PAYMENT_FIELDS) - set(columns)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From a performance perspective the difference will be neglible for a list this small, but using sets does make the code footprint a tad less and perhaps a bit easier to read. I'll update this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed in 985e235.
@@ -169,6 +175,12 @@ def _do_import(self, spreadsheet): | |||
def import_row(self, row_num, raw_row, import_context): | |||
search_id = self._parse_search_id(raw_row) | |||
fields_to_update = self._populate_updated_fields(raw_row) | |||
if ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is there a reason for this check to be during import and not earlier when uploading file?
is it because this could take really long so we don't want to do it then?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My main motivation for doing it here is that this is the part in the import where we're looping through all the sheet rows, and so we're able to easily see if there are cell values with empty required fields.
Doing this at an earlier point would mean we would have to do an extra loop through all the rows to validate their values which felt unnecessary. Additionally, failing it here simply results in the row not getting imported. This therefore then doesn't block the entire import and other rows can still get imported if they're valid.
@@ -297,7 +297,7 @@ def _create_bulk_configs(domain, request, case_upload): | |||
errors = [] | |||
for index, title in enumerate(worksheet_titles): | |||
with case_upload.get_spreadsheet(index) as spreadsheet: | |||
_, excel_fields, _ = _process_excel_mapping( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
double underscores!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah these were changed to double underscores otherwise they overshadow the gettext
import which is imported as _
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you think the double underscores don't look right, I can always change these to have variable names instead 🤔
@@ -227,6 +262,10 @@ def _perform_custom_case_import_operations(self, row_num, raw_row, fields_to_upd | |||
def user(self): | |||
return CouchUser.get_by_user_id(self.config.couch_user_id) | |||
|
|||
@cached_property |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good.
Just wanted to check once about testing on this. We have tested that this does not impact imports outside the feature flag i.e the blast radius is limited to only the feature flagged domains?
@mkangia With local testing everything looks fine. I tested with the following workflows:
All the code added in this PR sits behind the FF conditional, and so if it were to break anything I expect this would only be when (a) the FF is enabled and (b) a user is attempting a |
Product Description
If an Excel file import for the

payment
case type does not include headers for all the required fields, then the following error will be shown after continuing past step 2 of the import process:Additionally, if the import contains rows that either does not have values for the required fields, or sets values for the no edit fields, then the following errors will be shown in the import summary:

Technical Summary
Link to ticket here.
Link to tech spec here.
This PR adds some extra validation to the case import workflow when a user is importing cases for the
payment
case type. This extra validation seeks to ensure that all the necessary information exists on the case for payment verification.Feature Flag
MOBILE_USER_VERIFICATION
Safety Assurance
Safety story
Automated test coverage
Automated tests do exist.
QA Plan
No QA planned.
Rollback instructions
Labels & Review