Skip to content

fix: add missing gender, clientType and clientClassification in ClientProfileDetails screen#2578

Merged
therajanmaurya merged 5 commits intoopenMF:developmentfrom
amanna13:fix/missing-client-details-field
Jan 23, 2026
Merged

fix: add missing gender, clientType and clientClassification in ClientProfileDetails screen#2578
therajanmaurya merged 5 commits intoopenMF:developmentfrom
amanna13:fix/missing-client-details-field

Conversation

@amanna13
Copy link
Contributor

@amanna13 amanna13 commented Jan 17, 2026

Fixes - Jira-#579

  • Created separate database entities for gender, client type, and client classification following the same pattern as ClientStatusEntity
  • Added ClientGenderEntity, ClientTypeEntity, ClientClassificationEntity in core/database
  • Register converters in the CustomTypeConverters for serializing/deserializing these entities to/from JSON
  • Added GetGenderOptions, GetClientTypeOptions, GetClientClassificationOptions in core/network and updated the ClientMapper accordingly.
  • Updated ClientProfileDetailsViewModel to access data properly instead of hardcoded "Not Available" fallback

Note

GenderOptions, ClientTypeOptions, ClientClassificationOptions.kt though present in the core/model/objects/organisations was never used. For consistency we have added new models in the core/network and kept the old files as is.

Before After
image image

Also did respective changes in the ClientEditDetailsScreen

image image

Please make sure these boxes are checked before submitting your pull request - thanks!

  • Run the static analysis check ./gradlew check or ci-prepush.sh to make sure you didn't break anything

  • If you have multiple commits please combine them into one commit by squashing them.

Related PR - #2517

Summary by CodeRabbit

  • New Features
    • Added client gender, client type, and client classification fields across profiles and edit screens.
    • Profiles now display these attributes with "not available" fallbacks when missing.
    • Edit screens populate and enable dropdowns for these fields and include them in data sync.
    • Dropdown options are driven by available server-provided lists for each field.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Jan 17, 2026

📝 Walkthrough

Walkthrough

Adds client gender, type, and classification across layers: new Room entities and converters, new network DTOs and response fields, mapper mappings between network and DB sub-entities, DB entity extensions, and UI/viewmodel initialization and display adjustments.

Changes

Cohort / File(s) Summary
Database Entities
core/database/src/commonMain/kotlin/com/mifos/room/entities/client/ClientClassificationEntity.kt, core/database/src/commonMain/kotlin/com/mifos/room/entities/client/ClientGenderEntity.kt, core/database/src/commonMain/kotlin/com/mifos/room/entities/client/ClientTypeEntity.kt
Added three new Room entities (@Entity, @Parcelize, @Serializable) each with @PrimaryKey(autoGenerate = true) val id: Int = 0 and val name: String? = null.
Database Entity Extension
core/database/src/commonMain/kotlin/com/mifos/room/entities/client/ClientEntity.kt
Added nullable fields to ClientEntity: gender: ClientGenderEntity? = null, clientType: ClientTypeEntity? = null, clientClassification: ClientClassificationEntity? = null.
Type Converters
core/database/src/commonMain/kotlin/com/mifos/room/typeconverters/CustomTypeConverters.kt
Added JSON (de)serializers: from/to for ClientGenderEntity, ClientTypeEntity, and ClientClassificationEntity to persist sub-entities as strings.
Network Models
core/network/src/commonMain/kotlin/com/mifos/core/network/model/GetClientClassificationOptions.kt, .../GetClientTypeOptions.kt, .../GetGenderOptions.kt
Added three @Serializable DTOs: GetClientClassificationOptions, GetClientTypeOptions, GetGenderOptions with id: Long? and name: String?.
Network Response Extension
core/network/src/commonMain/kotlin/com/mifos/core/network/model/GetClientsPageItemsResponse.kt
Added optional fields: gender: GetGenderOptions? = null, clientType: GetClientTypeOptions? = null, clientClassification: GetClientClassificationOptions? = null.
Client Mapper
core/network/src/commonMain/kotlin/com/mifos/core/network/mappers/clients/ClientMapper.kt
Added bidirectional mappings between network DTOs and DB sub-entities for gender, clientType, and clientClassification (updated mapFromEntity and mapToEntity).
UI ViewModel & Screen
feature/client/src/commonMain/kotlin/.../ClientProfileDetailsViewModel.kt, feature/client/src/commonMain/kotlin/.../clientEditDetails/ClientEditDetailsScreen.kt
Display and edit initialization updated to read gender, clientType, clientClassification names/ids with fallbacks; dropdown options now derived from option lists and enabled when options exist.

Sequence Diagram(s)

mermaid
sequenceDiagram
participant API as "Remote API\n(GetClientsPage)"
participant Mapper as "ClientMapper"
participant NetworkModel as "Get*Options DTOs"
participant DB as "Room DB\nClientEntity + sub-entities"
participant UI as "ViewModel / Screen"

API->>Mapper: fetch GetClientsPageItemsResponse (includes gender/type/classification)
Mapper->>NetworkModel: map response → GetGenderOptions / GetClientTypeOptions / GetClientClassificationOptions
Mapper->>DB: construct ClientEntity with ClientGenderEntity / ClientTypeEntity / ClientClassificationEntity
DB->>UI: DAO exposes stored ClientEntity (with embedded sub-entities)
UI->>Mapper: request mappings to domain/network DTOs for display/edit

rect rgba(100,149,237,0.5)
note over Mapper,DB: CustomTypeConverters serialize/deserialize sub-entities as JSON when persisting
end

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • biplab1
  • itsPronay

Poem

🐇 I hopped through models, fields in tow,
gender, type, classification in a row,
From API to DB I made the leap,
Mapped and shown for screens to keep,
A tiny rabbit cheer — data in flow!

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
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 (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: adding missing gender, clientType, and clientClassification fields to the ClientProfileDetails screen.

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

✨ Finishing touches
  • 📝 Generate docstrings

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.

Copy link

@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: 1

🤖 Fix all issues with AI agents
In
`@core/network/src/commonMain/kotlin/com/mifos/core/network/mappers/clients/ClientMapper.kt`:
- Around line 98-109: In mapToEntity, avoid always constructing empty option
objects; change the assignments for gender, clientType, and clientClassification
to conditional creations using Kotlin's safe-call with let (e.g.,
domainModel.gender?.let { GetGenderOptions(id = it.id?.toLong(), name = it.name)
}) so each field becomes null when the source is null; apply the same pattern
for clientType (GetClientTypeOptions) and clientClassification
(GetClientClassificationOptions) in the ClientMapper.mapToEntity function.
🧹 Nitpick comments (1)
core/database/src/commonMain/kotlin/com/mifos/room/typeconverters/CustomTypeConverters.kt (1)

187-215: LGTM!

The new TypeConverter pairs follow the established pattern in this file. They correctly handle nullable values and use kotlinx.serialization for JSON encoding/decoding.

Minor observation: These converters use explicit type parameters (e.g., Json.decodeFromString<ClientGenderEntity>(it)) while some existing converters rely on type inference (e.g., toClientStatus at line 184). Both approaches work correctly, but you may consider aligning the style for consistency.

@amanna13 amanna13 force-pushed the fix/missing-client-details-field branch from c017e90 to da2dbe1 Compare January 17, 2026 20:24
Copy link

@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: 0

Caution

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

⚠️ Outside diff range comments (1)
feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditDetails/ClientEditDetailsScreen.kt (1)

621-648: Enable selection even when values are missing.

With the new defaults (empty strings), enabled = clientType.isNotEmpty()/clientClassification.isNotEmpty() prevents users from filling missing data. Gate on list availability instead.

✅ Proposed fix
-                MifosTextFieldDropdown(
-                    enabled = clientType.isNotEmpty(),
+                MifosTextFieldDropdown(
+                    enabled = list.isNotEmpty(),
                     value = clientType,
                     onValueChanged = { clientType = it },
                     onOptionSelected = { index, value ->
                         clientType = value
                         selectedClientTypeId = list[index].id
                     },
                     label = stringResource(Res.string.feature_client_client),
                     options = list.sortedBy { it.id }.map { it.name },
                     readOnly = true,
                 )
-                MifosTextFieldDropdown(
-                    enabled = clientClassification.isNotEmpty(),
+                MifosTextFieldDropdown(
+                    enabled = list.isNotEmpty(),
                     value = clientClassification,
                     onValueChanged = { clientClassification = it },
                     onOptionSelected = { index, value ->
                         clientClassification = value
                         selectedClientClassificationId = list[index].id
                     },
                     label = stringResource(Res.string.feature_client_client_classification),
                     options = list.sortedBy { it.id }.map { it.name },
                     readOnly = true,
                 )
🧹 Nitpick comments (1)
core/network/src/commonMain/kotlin/com/mifos/core/network/mappers/clients/ClientMapper.kt (1)

104-115: Inconsistent use of it inside .let blocks for clientType and clientClassification.

The gender mapping correctly uses it.id and it.name (lines 100-101), but clientType and clientClassification redundantly access the outer scope (domainModel.clientType?.id, domainModel.clientClassification?.id) instead of using the it reference. While functionally equivalent, this is inconsistent and defeats the clarity benefit of using .let.

♻️ Proposed fix for consistency
             clientType = domainModel.clientType?.let {
                 GetClientTypeOptions(
-                    id = domainModel.clientType?.id?.toLong(),
-                    name = domainModel.clientType?.name,
+                    id = it.id?.toLong(),
+                    name = it.name,
                 )
             },
             clientClassification = domainModel.clientClassification?.let {
                 GetClientClassificationOptions(
-                    id = domainModel.clientClassification?.id?.toLong(),
-                    name = domainModel.clientClassification?.name,
+                    id = it.id?.toLong(),
+                    name = it.name,
                 )
             },

@amanna13 amanna13 force-pushed the fix/missing-client-details-field branch from da2dbe1 to d93ee45 Compare January 17, 2026 20:34
@biplab1
Copy link
Contributor

biplab1 commented Jan 19, 2026

@amanna13 In the edit screen, when the gender and classification types are not available in the back-end, are dropdowns disabled automatically?

@amanna13
Copy link
Contributor Author

@amanna13 In the edit screen, when the gender and classification types are not available in the back-end, are dropdowns disabled automatically?

@biplab1 For gender the dropdown is available even if its not available.

            clientTemplate.genderOptions?.let { list ->
                MifosTextFieldDropdown(
                    enabled = list.isNotEmpty(),
                    value = gender,
                    onValueChanged = { gender = it },
........

but for clientType and classificationType its disabled automatically if those are not available.

            clientTemplate.clientTypeOptions?.let { list ->
                MifosTextFieldDropdown(
                    enabled = clientType.isNotEmpty(),
                    value = clientType,
                    onValueChanged = { clientType = it },
WhatsApp.Video.2026-01-19.at.7.09.40.PM.mp4

You can have a look into this. Though these were there previously, I didn't touch these section in the code.

@biplab1
Copy link
Contributor

biplab1 commented Jan 19, 2026

I had checked it earlier, after I added gender and client classification codes in the back-end via web-app, the Gender drop-down menu was working and Client Classification was still not working, the last one is what you have fixed.

So, currently make sure that both the cases are handled properly:

  1. If Gender and Client Classification are available, then drop-down menu should be enabled and
  2. If they are not setup in the back-end they should show a disabled drop-down menu.

@biplab1
Copy link
Contributor

biplab1 commented Jan 19, 2026

Can you check the order of the codes sent in the API response? I believe the back-end sorts the codes based on position field and no sorting would be required in front-end.

Also, make sure the API responses are completely consumed by the data classes even if those fields are not used in the app currently.

@amanna13
Copy link
Contributor Author

amanna13 commented Jan 19, 2026

@biplab1 yes, you are right. I checked it, the back-end automatically sorts the codes based on position field. Currently the frontend again adjusts it based on the id. So should I go ahead and make the changes.

@biplab1
Copy link
Contributor

biplab1 commented Jan 20, 2026

@amanna13 Yes, please go ahead, the sorting code in the front-end is redundant.

@amanna13
Copy link
Contributor Author

amanna13 commented Jan 20, 2026

Also, make sure the API responses are completely consumed by the data classes even if those fields are not used in the app currently.

@biplab1 I have tested with postman, The API response returns this below (for client id = 3)

    "gender": {
        "id": 28,
        "name": "Male"
    },
    "clientType": {
        "id": 24,
        "name": "Mobile"
    },
    "clientClassification": {
        "id": 34,
        "name": "Student"
    },

Notice that these don't have those extra fields configured yet - position, description, active, mandatory

@biplab1
Copy link
Contributor

biplab1 commented Jan 21, 2026

Understood,. Can you push the latest updates so that I can do a final review?

@amanna13 amanna13 changed the title fix: add missing gender, clientType and clientClassification in ClientProfileDetails screem fix: add missing gender, clientType and clientClassification in ClientProfileDetails screen Jan 21, 2026
Copy link

@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: 1

🤖 Fix all issues with AI agents
In
`@feature/client/src/commonMain/kotlin/com/mifos/feature/client/clientEditDetails/ClientEditDetailsScreen.kt`:
- Around line 491-503: The dropdowns in ClientEditDetailsScreen are currently
enabled based on the current selected value (e.g., gender.isNotEmpty()) which
prevents selection when a value is missing; update each MifosTextFieldDropdown
(e.g., the gender block inside clientTemplate.genderOptions?.let { list -> ...
}) to use the options list emptiness as the enabled condition (enabled =
list.isNotEmpty()) instead of checking the field value, and apply the same
change to the other similar blocks referenced (the blocks around the 621-633 and
636-648 ranges) so all dropdowns enable when options are available.

@amanna13
Copy link
Contributor Author

amanna13 commented Jan 21, 2026

@biplab1 Updated screenshot attached below (This will be in the case when the options are not configured in the backend)

WhatsApp.Video.2026-01-21.at.8.22.14.PM.mp4

When the options are configured

Screen_recording_20260121_215431.mp4

@amanna13 amanna13 requested a review from biplab1 January 21, 2026 16:26
Copy link
Contributor

@biplab1 biplab1 left a comment

Choose a reason for hiding this comment

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

Some minor changes requested.

Looks good to me. This can be merged.

@therajanmaurya therajanmaurya merged commit 17e3e3e into openMF:development Jan 23, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants