Skip to main content

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.tsx
  • apps/mobile/src/navigation/RootNavigator.tsx
  • apps/mobile/src/screens/loginScreen/index.tsx
  • apps/mobile/src/screens/branchScreen/index.tsx
  • apps/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 versionCode through AppVersionModule.
  • JavaScript reads native version data through each app boundary: apps/mobile/src/native/appVersion.ts and apps/pos-terminal/src/native/appVersion.ts.
  • The screen reads Firestore version/vapp.
  • Required-update logic lives in apps/mobile/src/services/appUpdate.ts and apps/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 / androidVersion
    • iosVersionNumber / 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 UserSelectionScreen and 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 userId exists
  • 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:
    • allBranches from GET /api/branches?userCode=999999, used as the branch catalog
    • userBranches from GET /api/branches?userCode={loggedInUserCode}, used to check access
  • Step 1 of the screen is selecting a main branch from allBranches.
  • The app compares the selected branch code with userBranches using hasMainBranchAccess. Codes are trimmed and resolved from whsGrpCode, whGrpCode, or BranchCode.
  • After a main branch is selected, the app always calls getWarehouses() (GET /api/warehouses?pageLimit=40&page=1).
  • The app always calls getWarehousesSub(branchCode) (GET /api/warehouses/{whGrpCode}/sub), even when the selected branch is absent from userBranches.
  • Warehouse options exclude codes containing NF- or DR-. Sub-warehouse options also exclude the selected branch code and codes already present in that branch's main-warehouse list.
  • Main warehouses appear first and only for an assigned branch. If an assigned branch has no main warehouses in the filtered API result, the app falls back to the selected branch's code and name as its main-warehouse option.
  • For an unassigned branch, main warehouses remain hidden, but sub-warehouses returned by the API are available after filtering.
  • ซิ้งค์ข้อมูลคลังใหม่ calls syncWarehouses(), waits two seconds, then reloads both warehouse lists. The current userBranches state controls only main-warehouse visibility, not whether sub-warehouses are loaded.
  • Step 2 of the screen is selecting the actual warehouse branch to store locally.
  • On warehouse selection, the app:
    • for a main warehouse, reloads the logged-in user's branches and checks access again before saving; if access was removed, returns to step 1 with ไม่มีสิทธิเลือกคลังหลักของสาขานี้
    • 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:

  • BranchId is the selected main branch id
  • BranchCode is the selected main branch code
  • whsGrpCode is the actual warehouse code selected in step 2
  • whsGrpName is the selected warehouse label
  • isMain shows 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.
  • TransferWarehouseDetail now uses stored BranchCode to load warehouse options via getWarehousesSub(BranchCode), while still using the stored whsGrpCode as 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_date is 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:
    • deptCode from 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.

Notes​

  • Login validity is date-based, so the stored session expires when the saved login date is no longer equal to the current day.
  • Branch exists 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.