App startup and role detection
After login the app fetches the user's tenant, roles and work areas, decides whether the user is a Cadre or Unit In-Charge/FMT L1, and sends them to the right next screen.
FactsheetOnboarding & setup
- Who uses it
- CadreUnit In-Charge / FMT L1
- How you get here
- Runs automatically on every launch after the language screen.
- Tables
worknodehierarchy- APIs
- 3 calls today, 5 App Service operations
- Offline
- Returning users with complete data start fully offline. A fresh setup needs internet.
Screens
| Screen | What it does | Source |
|---|---|---|
| Splash | Progress spinner while startup decisions run. | app/src/main/java/org/platformcommons/urvi/view/splash/SplashActivity.kt |
Rules
Conditions from the code, rewritten as plain decision rules.
| When | Then |
|---|---|
| There is a Bridge account and PREF_KEY_ALL_SYNCS_COMPLETE is true | Go straight to Home, with no network needed. |
| There is an account, downloads are not complete, and a Village/Habitation/VO was saved earlier | Resume the cadre Data download screen. |
| This is a fresh login with no internet | Show "Error / internet not available"; OK closes the app. |
| The user profile call fails or returns nothing | Show "Sorry, We are not able to process your request at the moment"; OK closes the app. |
| Tenant is ap.gov and any role code contains unit-incharge or fmt_l1 | Mark the user as Unit login and, after the hierarchy download, open the Unit data download screen. |
| Tenant is ap.gov and the user is not Unit | Treat as Cadre and, after the hierarchy download, open Village/Habitation/VO selection. |
| The Village → Habitation → VO hierarchy download fails | Show "We are unable to process your request due to some technical issue"; OK clears all app data and restarts the splash. |
API contracts
Each call opens to its use case, headers, request and response bodies, and errors.
| Today: call | Use | Replaced by |
|---|---|---|
POST /ctld/api/session/v1 | Sign the user in and get a session token. | |
GET /rtld/api/dataset/v1/execute?name=PlusOneTenantUserData | Load the signed-in user, tenant, roles and assigned work nodes; decides cadre vs Unit In-charge/FMT flow. | |
SDK Firebase Remote Config | Read the show_force_sync flag (show_analytics_tab and current_season_value are fetched but unused). |
| App Service v2: operation | Use |
|---|---|
POST /auth/login | Log in with login, tenant and password |
POST /auth/refresh | Rotate the refresh token |
GET /session/bootstrap | Session bootstrap after login and on cold start |
GET /config | Typed config bundle (ETag) |
PUT /devices/{deviceId} | Register or update this device |
Behaviour notes
- Saves tenant and user preferences: KEY_TENANT_ID, KEY_TENANT_LOGIN, KEY_TENANT_NAME, KEY_USER_ID, KEY_USER_FIRST_NAME, KEY_USER_LOGIN, KEY_USER_ROLES, KEY_FACILITY_DATA, KEY_IS_UNIT_LOGIN, KEY_ACCOUNT, HEADER_SESSION_ID. The old database is cleared.
- Role checks are substring matches; fmt_l1 would also match a hypothetical fmt_l10.
- Possible bug · unverified the hierarchy uses synthetic ids (habitation = village x 100 + index, VO = habitation x 100 + index), which collide if a village has 100 or more habitations or a habitation has 100 or more VOs.
- The returning-user path has no internet check and uses whatever role JSON was last cached.
Improve in the rewrite
- Replace the scattered flags (isLanguageSelected, setupStatus, PREF_KEY_ALL_SYNCS_COMPLETE, KEY_IS_SETUP_COMPLETED, KEY_IS_UNIT_LOGIN) with one persisted state machine: NoLanguage → NoAccount → NoRole → NeedsWorkNode → Downloading → Ready.
- Match role codes exactly instead of by substring.
- Use the server's real ids for villages, habitations and VOs.