Login To Branch To Home
This page documents the current mobile startup flow based on the implementation in apps/mobile.
Scope
This workflow is based on:
apps/mobile/App.tsxapps/mobile/src/navigation/RootNavigator.tsxapps/mobile/src/screens/loginScreen/index.tsxapps/mobile/src/screens/branchScreen/index.tsxapps/mobile/src/screens/homeScreen/index.tsx
Startup decision flow
Step 1. Login
The login screen collects username and password, then calls the auth service.
Required app update check
- The login screen reads the native app
versionCodethroughAppVersionModule. - JavaScript reads native version data through each app boundary:
apps/mobile/src/native/appVersion.tsandapps/pos-terminal/src/native/appVersion.ts. - The screen reads Firestore
version/vapp. - Required-update logic lives in
apps/mobile/src/services/appUpdate.tsandapps/pos-terminal/src/services/appUpdate.ts. - The current check compares numeric values after converting both sides with
Number(...). - The main remote field is
versionNumber; the implementation also accepts platform-specific shapes if they are added later:androidVersionNumber/androidVersioniosVersionNumber/iosVersion- nested
android.versionNumber/android.version - nested
ios.versionNumber/ios.version
- If the Firestore version number is greater than the native
versionCode, the app shows a blocking modal:แอปของคุณจำเป็นต้องอัปเดทเป็นเวอร์ชั่น .... - The modal displays the numeric value from Firestore
versionNumber. - The modal has no close action and ignores Android back dismiss requests.
- POS Terminal runs the same check on
UserSelectionScreenand blocks with the same modal before login actions can continue.
Main behavior
- If username or password is missing, the app blocks submission and shows an alert.
- On successful login, the app:
- stores the auth token
- stores the serialized user object
- stores the login date in
DD-MM-YYYY - refreshes the FCM token when possible
- patches user permissions or flags back to the backend when
userIdexists
- Before finishing login, the app runs
verifyAlcoholCheckBeforeLogin. - If the login API reports missing required values, the screen switches into password-reset mode.
Output of the login step
isAuthenticated = true- branch is still unresolved until branch selection is completed
Step 2. Branch selection
After login, if no branch is stored, RootNavigator renders the branch-selection flow.
Main behavior
- The screen loads two branch lists:
allBranchesfrom fallback user code999999userBranchesfrom the current stored user code
- Step 1 of the screen is selecting a main branch.
- After a main branch is selected, the app loads warehouse options for that branch by calling:
getWarehouses()for the global main-warehouse listgetWarehousesSub(branch.whsGrpCode)for sub-warehouses under the selected branch
- The app removes any sub-warehouse whose
whsCodealready exists in the main-warehouse list. - If the selected branch also exists in
userBranches, the app prepends the selected main warehouse itself back into the option list. - Step 2 of the screen is selecting the actual warehouse branch to store locally.
- On warehouse selection, the app:
- clears cached tax data
- saves the selected branch into storage
- notifies the navigator that branch selection is complete
- fetches tax data as a best-effort background step
Firestore inventory index diagnostic
- Long-press a warehouse in step 2 to run the same real-time Firestore inventory query used by the product picker for that warehouse. The normal tap action is suppressed, so the warehouse is not selected.
- The temporary listener logs each received snapshot and stops automatically after five seconds. Starting a new diagnostic stops any previous listener first.
- If Firestore rejects the query because a composite index is missing, the console prints
[FIRESTORE CREATE INDEX]followed by the Firebase Console URL as a separate entry. React Native DevTools exposes that URL as a clickable link.
Stored branch payload
The selected branch is stored as a single JSON object in local storage under the branch key.
The payload shape is:
{
BranchId: string | number;
BranchCode: string;
whsGrpName: string;
whsGrpCode: string;
isMain: boolean;
}
Meaning:
BranchIdis the selected main branch idBranchCodeis the selected main branch codewhsGrpCodeis the actual warehouse code selected in step 2whsGrpNameis the selected warehouse labelisMainshows whether the selected warehouse is the main warehouse of that branch
Downstream usage note
- Screens and services that need the selected warehouse typically read
whsGrpCode. - Screens that need the owning main branch code can read
BranchCode. TransferWarehouseDetailnow uses storedBranchCodeto load warehouse options viagetWarehousesSub(BranchCode), while still using the storedwhsGrpCodeas the selected source warehouse for item and batch flows.
Step 3. Home
When both auth and branch selection are satisfied, RootNavigator renders Home.
Main behavior
- Home loads stored user data and selected branch from local storage.
- Home checks the saved login date whenever it receives focus; if the stored
login_dateis no longer the current day, Home uses the normal mobile logout behavior. - Home header runs the same required app update check as Login, including when Home regains focus.
- POS Terminal Home also reruns the required app update check when it regains focus.
- The visible menu depends on:
deptCodefrom the authenticated user- whether the selected branch is marked as
isMain
- Menu cards route the user into the rest of the POS flows such as:
- order list
- booking price
- invoice list
- shipping
- storefront
- stock flows
- customer and employee screens
- Logout from the home header clears all session storage and returns the app to the login state.
Navigation states in RootNavigator
Notes
- Login validity is date-based, so the stored session expires when the saved login date is no longer equal to the current day.
Branchexists as a screen inside the authenticated stack, so users can re-open branch selection after reaching Home.- The Home screen is both a landing page and a permission gate for downstream workflows.