Skip to content

Mhwc 141 card mooving issue#136

Merged
DeepakKumar471 merged 3 commits intorelease-4.0from
mhwc-141-card-mooving-issue
Feb 20, 2026
Merged

Mhwc 141 card mooving issue#136
DeepakKumar471 merged 3 commits intorelease-4.0from
mhwc-141-card-mooving-issue

Conversation

@DeepakKumar471
Copy link
Copy Markdown
Contributor

@DeepakKumar471 DeepakKumar471 commented Feb 19, 2026

📋 Description

JIRA ID: mHWC-141

Please provide a summary of the change and the motivation behind it. Include relevant context and details.
Conflict resolved

✅ Type of Change

  • 🐞 Bug fix (non-breaking change which resolves an issue)
  • New feature (non-breaking change which adds functionality)
  • 🔥 Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • 🛠 Refactor (change that is neither a fix nor a new feature)
  • ⚙️ Config change (configuration file or build script updates)
  • 📚 Documentation (updates to docs or readme)
  • 🧪 Tests (adding new or updating existing tests)
  • 🎨 UI/UX (changes that affect the user interface)
  • 🚀 Performance (improves performance)
  • 🧹 Chore (miscellaneous changes that don't modify src or test files)

ℹ️ Additional Information

Please describe how the changes were tested, and include any relevant screenshots, logs, or other information that provides additional context.

Summary by CodeRabbit

  • Bug Fixes

    • Added explicit duplicate beneficiary detection with user alert notification.
    • Improved error handling with automatic retry fallback and user error dialogs for failed operations.
    • Enhanced data validation during patient information persistence.
  • New Features

    • Enhanced PDF generation with improved context awareness.
    • Improved user notifications for operation completion and status.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Feb 19, 2026

📝 Walkthrough

Walkthrough

PersonalDetailsFragment refactored to replace DispatcherProvider-based coroutine dispatching with direct Dispatchers.IO/Main calls. Added explicit duplicate beneficiary check with user alert, consolidated data population logic, implemented retry-on-failure patient persistence with fallback field clearing, and updated PDF generation for API 33 context-awareness using Pair<OutputStream, Uri>.

Changes

Cohort / File(s) Summary
Coroutine Dispatch Refactoring
app/src/main/java/org/piramalswasthya/cho/ui/commons/personal_details/PersonalDetailsFragment.kt
Replaced DispatcherProvider-based coroutine launches and withContext calls with direct Dispatchers.IO and Dispatchers.Main usage throughout the fragment.
Ben-Visit & Data Persistence
app/src/main/java/org/piramalswasthya/cho/ui/commons/personal_details/PersonalDetailsFragment.kt
Added explicit duplicate check by beneficiaryRegID/ID with user-visible alert; consolidated location/master data population into inlined blocks; reworked patient persistence with direct Patient object construction, inline save attempt, constraint-failure fallback that clears foreign-key fields and retries, and error dialog on final failure.
PDF Generation & Notifications
app/src/main/java/org/piramalswasthya/cho/ui/commons/personal_details/PersonalDetailsFragment.kt
Refactored createPdfForApi33() to accept Context and return Pair<OutputStream, Uri>; unified PDF creation flow for both public downloads and MediaStore entries; adjusted completion notifications to emit shared helper with paired (fileName, uri) data.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • Mhwc 141 card mooving issue #134: Modifies the same PDF-generation code in PersonalDetailsFragment, changing createPdfForApi33 signature to accept Context and return Pair<OutputStream, Uri> for coordinated download notifications.

Suggested labels

bug

Suggested reviewers

  • sushant-bizbrolly

Poem

🐰 A fragment transformed, dispatchers aligned,
Duplicates caught where the patients were signed,
PDFs now flow in pairs, oh what cheer!
With retry logic and fallbacks sincere,
Our code hops along—refactored and clear! 📄

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Title check ⚠️ Warning The PR title 'Mhwc 141 card mooving issue' does not clearly align with the actual changes, which involve refactoring dispatcher usage, adding duplicate beneficiary checks, consolidating data population logic, and improving PDF generation and error handling. Revise the title to accurately reflect the main changes, such as 'Refactor PersonalDetailsFragment coroutine dispatchers and improve patient save flow' or a similar description that captures the core refactoring work.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch mhwc-141-card-mooving-issue

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@sonarqubecloud
Copy link
Copy Markdown

@DeepakKumar471 DeepakKumar471 changed the base branch from main to release-4.0 February 19, 2026 13:40
@DeepakKumar471
Copy link
Copy Markdown
Contributor Author

@coderabbitai full review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Feb 19, 2026

✅ Actions performed

Full review triggered.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
app/src/main/java/org/piramalswasthya/cho/ui/commons/personal_details/PersonalDetailsFragment.kt (1)

272-292: ⚠️ Potential issue | 🟠 Major

Data race on shared Patient object + inconsistent duplicate-detection semantics

patient here is the live object from the adapter's dataset. Mutating patient.patientID = existing.patientID on Dispatchers.IO while the RecyclerView may concurrently be binding views that read from the same object is a data race. Use a defensive copy (e.g., patient.copy(patientID = existing.patientID)) before modifying.

Additionally, this path performs a duplicate check on beneficiaryRegID, whereas savePatientFromSearch (the other patient-save path) checks beneficiaryID. These inconsistent keys mean a patient found by one check may slip through the other, producing duplicate rows.

🛠️ Suggested fix
- val patient = benVisitInfo.patient
- val regId = patient.beneficiaryRegID
+ val regId = benVisitInfo.patient.beneficiaryRegID
  if (regId != null) {
      val existing = patientDao.getPatientByBenRegId(regId)
      if (existing == null) {
-         patientDao.insertPatient(patient)
+         patientDao.insertPatient(benVisitInfo.patient)
      } else {
-         patient.patientID = existing.patientID
-         patientDao.updatePatient(patient)
+         patientDao.updatePatient(benVisitInfo.patient.copy(patientID = existing.patientID))
      }
  } else {
-     patientDao.insertPatient(patient)
+     patientDao.insertPatient(benVisitInfo.patient)
  }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@app/src/main/java/org/piramalswasthya/cho/ui/commons/personal_details/PersonalDetailsFragment.kt`
around lines 272 - 292, The code mutates the live adapter Patient object on
Dispatchers.IO and uses a different dedupe key than savePatientFromSearch; to
fix, create a defensive copy of the patient (e.g., from benVisitInfo.patient)
before any mutation or DB operations and operate on that copy (do not assign to
patient.patientID on the original), and unify the duplicate-detection key with
the rest of the codebase (use the same field checked in savePatientFromSearch —
beneficiaryID — instead of beneficiaryRegID) when calling
patientDao.getPatientBy... so inserts/updates use the copy and the consistent
identifier (update the copy's patientID from the existing row before calling
patientDao.updatePatient or insertPatient).
🧹 Nitpick comments (2)
app/src/main/java/org/piramalswasthya/cho/ui/commons/personal_details/PersonalDetailsFragment.kt (2)

1307-1320: createPdfForApi33 name mismatches its actual API guard

The function is invoked for all devices running API ≥ Build.VERSION_CODES.Q (29), not just API 33. The misleading name could cause future callers to skip the guard and call it unconditionally on older devices. Rename it to e.g. createPdfForApi29Plus or createPdfWithMediaStore.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@app/src/main/java/org/piramalswasthya/cho/ui/commons/personal_details/PersonalDetailsFragment.kt`
around lines 1307 - 1320, The call site uses createPdfForApi33 for all devices
API >= Q (29) which is misleading; rename the function and all its references to
a name that matches the actual API guard (e.g., createPdfForApi29Plus or
createPdfWithMediaStore) and update its declaration, usages (including the call
in PersonalDetailsFragment where you check Build.VERSION.SDK_INT >=
Build.VERSION_CODES.Q), and any related docs/comments so the name accurately
reflects it runs for Q/29+ rather than only 33.

421-427: Redundant withContext(Dispatchers.Main) inside an already-Main coroutine

lifecycleScope.launch { … } without an explicit dispatcher runs on Dispatchers.Main.immediate. The withContext(Dispatchers.Main) blocks nested inside collect { … } (lines 421–427, 439–445, 457–463, 475–483) are therefore no-ops and only add noise. If background work needs to be dispatched, add withContext(Dispatchers.IO) around the DB/IO calls instead.

♻️ Proposed fix (representative block — same pattern on all four collectors)
  lifecycleScope.launch {
      viewModel.patientListForNurse?.collect {
          itemAdapter?.submitList(it.sortedByDescending { item -> item.patient.registrationDate })
          patientCount = it.size
-         withContext(Dispatchers.Main) {
-             if (!isShowingSearchResults) {
-                 binding.patientListContainer.patientList.adapter = itemAdapter
-                 binding.patientListContainer.patientCount.text =
-                     it.size.toString() + getResultStr(it.size)
-             }
+         if (!isShowingSearchResults) {
+             binding.patientListContainer.patientList.adapter = itemAdapter
+             binding.patientListContainer.patientCount.text =
+                 it.size.toString() + getResultStr(it.size)
          }
      }
  }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@app/src/main/java/org/piramalswasthya/cho/ui/commons/personal_details/PersonalDetailsFragment.kt`
around lines 421 - 427, The withContext(Dispatchers.Main) calls inside the
collectors in PersonalDetailsFragment.kt are redundant because
lifecycleScope.launch runs on Dispatchers.Main.immediate; remove those nested
withContext(Dispatchers.Main) blocks (the ones wrapping adapter assignment and
patient count updates) and leave the UI updates directly in the collector; if
any preceding work in the collector is doing DB/IO, move that work into
withContext(Dispatchers.IO) (or off-main coroutine) and keep only the UI update
lines (adapter assignment and binding.patientListContainer.patientCount.text =
...) on the main coroutine.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@app/src/main/java/org/piramalswasthya/cho/ui/commons/personal_details/PersonalDetailsFragment.kt`:
- Around line 1382-1396: The createPdfForApi33 function uses unsafe !! and dead
Objects.requireNonNull calls and lacks an API level annotation; change
createPdfForApi33 to be annotated `@RequiresApi`(Build.VERSION_CODES.Q), remove
the Objects.requireNonNull lines, and replace the pdfUri?.let { ... }!! with
explicit null checks: first call context.contentResolver.insert(...) into pdfUri
and if null throw an IOException with a clear message, then call
context.contentResolver.openOutputStream(pdfUri) into outst and if null throw an
IOException with a clear message, finally return Pair(outst, pdfUri) after the
validated non-null checks so callers get meaningful errors instead of a raw NPE.
- Around line 526-540: The existence check currently only runs when
beneficiaryID != null, allowing duplicates when beneficiaryID is null; update
savePatientFromSearch to also check beneficiaryRegID (use
patientDao.getByBeneficiaryRegId or add one if missing) before inserting and
consider both identifiers when calling patientDao.getBen/generic lookup to
prevent duplicates even if beneficiaryID is null, and replace the hardcoded
dialog title/message in the MaterialAlertDialogBuilder with string resources
(R.string.patient_already_exists and R.string.patient_already_exists_message) so
the same dialog is shown whenever either identifier matches; keep generateUuid()
for new patientID only after both checks pass.
- Around line 640-669: In PersonalDetailsFragment's save flow (where
patientRepo.insertPatient is called, using patientToSave and
patientWithNullForeignKeys), do three things: (1) never swallow exceptions — log
both caught exceptions (e and e2) with the logger/Log before handling UI so
stack traces are preserved; (2) eliminate the TOCTOU duplicate gap by making the
insert atomic: either perform the existence check + insert inside a single
database transaction or use an upsert/insert-with-conflict-resolution provided
by patientRepo (or explicitly query for existing by
beneficiaryID/beneficiaryRegID before deciding to insert/update) and on
SQLiteConstraintException inspect the constraint name/message to decide if it is
a FK violation (then retry with nullified FKs) versus a unique-key/duplicate
violation (then abort or merge rather than creating a new UUID); (3) extract
hardcoded dialog strings ("Error Saving Patient", "Failed to save patient…") to
R.string and use them for the MaterialAlertDialogBuilder.

---

Outside diff comments:
In
`@app/src/main/java/org/piramalswasthya/cho/ui/commons/personal_details/PersonalDetailsFragment.kt`:
- Around line 272-292: The code mutates the live adapter Patient object on
Dispatchers.IO and uses a different dedupe key than savePatientFromSearch; to
fix, create a defensive copy of the patient (e.g., from benVisitInfo.patient)
before any mutation or DB operations and operate on that copy (do not assign to
patient.patientID on the original), and unify the duplicate-detection key with
the rest of the codebase (use the same field checked in savePatientFromSearch —
beneficiaryID — instead of beneficiaryRegID) when calling
patientDao.getPatientBy... so inserts/updates use the copy and the consistent
identifier (update the copy's patientID from the existing row before calling
patientDao.updatePatient or insertPatient).

---

Nitpick comments:
In
`@app/src/main/java/org/piramalswasthya/cho/ui/commons/personal_details/PersonalDetailsFragment.kt`:
- Around line 1307-1320: The call site uses createPdfForApi33 for all devices
API >= Q (29) which is misleading; rename the function and all its references to
a name that matches the actual API guard (e.g., createPdfForApi29Plus or
createPdfWithMediaStore) and update its declaration, usages (including the call
in PersonalDetailsFragment where you check Build.VERSION.SDK_INT >=
Build.VERSION_CODES.Q), and any related docs/comments so the name accurately
reflects it runs for Q/29+ rather than only 33.
- Around line 421-427: The withContext(Dispatchers.Main) calls inside the
collectors in PersonalDetailsFragment.kt are redundant because
lifecycleScope.launch runs on Dispatchers.Main.immediate; remove those nested
withContext(Dispatchers.Main) blocks (the ones wrapping adapter assignment and
patient count updates) and leave the UI updates directly in the collector; if
any preceding work in the collector is doing DB/IO, move that work into
withContext(Dispatchers.IO) (or off-main coroutine) and keep only the UI update
lines (adapter assignment and binding.patientListContainer.patientCount.text =
...) on the main coroutine.

@DeepakKumar471 DeepakKumar471 self-assigned this Feb 20, 2026
@DeepakKumar471 DeepakKumar471 added the bug Something isn't working label Feb 20, 2026
@DeepakKumar471 DeepakKumar471 merged commit 89796cb into release-4.0 Feb 20, 2026
5 of 7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants