Preserve Over Limit Status#1151
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
WalkthroughThe change tightens cleanup logic in Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Review rate limit: 0/1 reviews remaining, refill in 60 minutes.Comment |
| if user_visit.status == VisitValidationStatus.duplicate: | ||
| flags.append(["duplicate", "A beneficiary with the same identifier already exists"]) | ||
| else: | ||
| elif user_visit.status == VisitValidationStatus.duplicate: |
There was a problem hiding this comment.
this would sound silly but I think this would be easier to understand if you just separate this completely out as
if user_visit.status == VisitValidationStatus.duplicate and (not opportunity_flags.duplicate):
user_visit.status = VisitValidationStatus.pending
I say so because the elif conditions seems to be not related to the if one at all.
There was a problem hiding this comment.
That's fair, and I can see it appearing a bit odd for other devs reviewing.
I've refactored the conditional in 1f57678.
mkangia
left a comment
There was a problem hiding this comment.
I guess a better thing would be to check for the duplicate flag requirement even further up when the duplicate is actually set but that could be a much bigger change
@mkangia I think that would logically make more sense, but I'm hesitant of doing a bigger refactor and potentially introducing a new bug. So my thinking was to do a minimal bug fix now, and a bigger logical refactoring can safely be done at a later point. |
| if user_visit.status == VisitValidationStatus.duplicate: | ||
| flags.append(["duplicate", "A beneficiary with the same identifier already exists"]) | ||
| else: | ||
| if user_visit.status == VisitValidationStatus.duplicate and not opportunity_flags.duplicate: |
There was a problem hiding this comment.
i think this would be slightly clearer as
elif user_visit.status == VisitValidationStatus.duplicate: or even
else:
if user_visit.status == VisitValidationStatus.duplicate:
but repeating the flag check makes it quite verbose and hard to tell that it is the opposite path as the block above
There was a problem hiding this comment.
That's a fair point. I did a force push to refactor this conditional according to Sravan's suggestion.
Addressed in 75a7ba4.
There was a problem hiding this comment.
aha,
@calellowitz
you suggested what Zandre originally wrote and I asked for a change here
You and I see code clarity a bit differently. In my head, it was NOT an "opposite path"
| @@ -276,7 +276,7 @@ def clean_form_submission(access: OpportunityAccess, user_visit: UserVisit, xfor | |||
| if opportunity_flags.duplicate: | |||
There was a problem hiding this comment.
Just throwing another option
if user_visit.status == VisitValidationStatus.duplicate:
if opportunity_flags.duplicate:
flags.append(["duplicate", "A beneficiary with the same identifier already exists"])
else:
user_visit.status = VisitValidationStatus.pending
There was a problem hiding this comment.
This is a nice approach, very clean. Will update.
There was a problem hiding this comment.
I did a force push to incorporate the above suggestion in the second commit.
Addressed in 75a7ba4.
sravfeyn
left a comment
There was a problem hiding this comment.
Nice find, LGTM except for the nit comments.
1f57678 to
75a7ba4
Compare
Product Description
Service-delivery submissions that exceed the per-worker
Max Service Deliveriescap will now be correctly rejected asOver Limit. Before this fix, the cap was silently ignored on opportunities where the duplicate verification flag was off, allowing workers to submit beyond their configured limit. There is no new UI or workflow — this restores the intended cap-enforcement behaviour on the backend.Technical Summary
Link to ticket here
This is a release path 1 feature — Improvements to existing features & quick wins
The cap-check in
process_deliver_unit()correctly setsuser_visit.status = over_limitwhen a worker exceeds theirOpportunityClaimLimit.max_visits, butclean_form_submission()ran immediately afterwards and unconditionally resetuser_visit.statusback topendingwheneverOpportunityVerificationFlags.duplicatewasFalse. Withauto_approve_visits=Truethe auto-approve branch then flipped thatpendingstraight toapproved, silently bypassing the cap. The function's docstring describes the intended behaviour as "resetting duplicate status when the duplicate flag is disabled" — the implementation was just broader than the intent. The fix scopes the reset to only act when the prior status isduplicate, leavingover_limitandtrialintact.commcare_connect/form_receiver/processor.py:280—else:→elif user_visit.status == VisitValidationStatus.duplicate:. No model, schema, or API changes.Safety Assurance
Safety story
status == duplicateandstatus == anything else) so that it now fires in only one (status == duplicate). Any code path that relied on the broader behaviour would have been overwritingover_limitortrial— neither of which is desirable. All existing tests inform_receiver/andopportunity/continue to pass (529 passed).UserVisitrows are not modified by this PR. Over-cap rows that pre-date the fix continue to show their current statuses until the separate remediation script is run.if opportunity_flags.duplicate:branch is unchanged; behaviour for that path is identical to before. Specifically covered by the existingtest_receiver_duplicateandtest_receiver_duplicate_concurrent_submissionstests.Automated test coverage
New regression test in
commcare_connect/form_receiver/tests/test_receiver_integration.py:test_over_limit_status_preserved_when_duplicate_flag_disabled— setsverification_flags={"duplicate": False}on the opportunity fixture, submits a form against a payment unit configured withdaily_max_per_user=0to force the cap to trigger on the very first submission, and asserts the resultingUserVisit.status == over_limit. Pre-fix this test fails withassert 'approved' == 'over_limit', exactly mirroring the prod symptom.Existing coverage that continues to validate the surrounding behaviour:
test_receiver_deliver_form_daily_visits_reached,test_receiver_deliver_form_max_visits_reached,test_receiver_deliver_form_end_date_reached— cap-enforcement happy paths (with defaultduplicate=True).test_receiver_duplicate,test_receiver_duplicate_concurrent_submissions— duplicate-flagging path, ensuring the touched conditional still preserves duplicate detection.QA Plan
QA will not be performed for this change. Below is the testing plan for reference:
OpportunityVerificationFlags.duplicate = Falseandauto_approve_visits = True.max_total(e.g. 2) to make the cap easy to hit.max_total.UserVisit.statusisover_limit(notapproved) on the worker-deliveries view in the org dashboard.CompletedWork.statusisover_limit.payment_accrueddoes not include the over-cap visit.duplicate = Trueto confirm the duplicate-detection path is unaffected: submit two visits with the sameentity_id; the second should be flagged asduplicate, notover_limitorpending.Labels & Review