ข้ามไปยังเนื้อหาหลัก

Login ไป Branch ไป Home

หน้านี้อธิบาย mobile startup flow ปัจจุบันจาก implementation จริงใน apps/mobile

อ้างอิงจากโค้ด

  • 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

ลำดับการตัดสินใจตอนเริ่มแอป

ขั้นที่ 1 Login

การตรวจเวอร์ชั่นที่บังคับอัปเดท

  • หน้า Login อ่าน native app versionCode ผ่าน AppVersionModule

  • JavaScript อ่าน native version ผ่าน boundary ของแต่ละแอป: apps/mobile/src/native/appVersion.ts และ apps/pos-terminal/src/native/appVersion.ts

  • หน้า Login อ่าน Firestore ที่ version/vapp

  • required-update logic อยู่ที่ apps/mobile/src/services/appUpdate.ts และ apps/pos-terminal/src/services/appUpdate.ts

  • การเช็คปัจจุบันแปลงค่าทั้งสองฝั่งด้วย Number(...) ก่อนเปรียบเทียบ

  • field หลักจาก Firestore คือ versionNumber; implementation ยังรองรับรูปแบบแยก platform ถ้าเพิ่มภายหลัง:

    • androidVersionNumber / androidVersion
    • iosVersionNumber / iosVersion
    • nested android.versionNumber / android.version
    • nested ios.versionNumber / ios.version
  • ถ้า version number จาก Firestore มากกว่า native versionCode แอปจะแสดง modal บังคับว่า แอปของคุณจำเป็นต้องอัปเดทเป็นเวอร์ชั่น ...

  • เลขเวอร์ชั่นใน modal ใช้ค่าตัวเลขจาก Firestore versionNumber

  • modal นี้ไม่มีปุ่มปิด และกด back ของ Android เพื่อปิดไม่ได้

  • POS Terminal ใช้ check เดียวกันบน UserSelectionScreen และแสดง modal บล็อกก่อนใช้งาน login ต่อ

  • ถ้า username หรือ password ไม่ครบ จะไม่ submit และแสดง alert

  • เมื่อ login สำเร็จ แอปจะ:

    • เก็บ auth token
    • เก็บ user object
    • เก็บ login date ในรูปแบบ DD-MM-YYYY
    • refresh FCM token ถ้าทำได้
    • patch user flags กลับไป backend ถ้ามี userId
  • ก่อนจบ login แอปจะเรียก verifyAlcoholCheckBeforeLogin

  • ถ้า API ตอบกลับว่า required values ไม่ครบ หน้าจอจะเปลี่ยนไปเป็น password reset mode

ขั้นที่ 2 เลือก Branch

  • ถ้ายังไม่มี branch ใน storage, RootNavigator จะ render branch-selection flow
  • หน้าจอจะโหลด branch list สองชุด:
    • allBranches จาก fallback user code 999999
    • userBranches จาก user code ของผู้ใช้ปัจจุบัน
  • step แรกคือเลือก main branch
  • จากนั้นแอปจะโหลด warehouse options ของ branch นั้นโดยเรียก:
    • getWarehouses() เพื่อเอารายการคลังหลักทั้งหมด
    • getWarehousesSub(branch.whsGrpCode) เพื่อเอารายการคลังย่อยของสาขาที่เลือก
  • แอปจะตัดคลังย่อยที่มี whsCode ซ้ำกับรายการคลังหลักออก
  • ถ้าสาขาที่เลือกมีอยู่ใน userBranches ด้วย แอปจะ prepend คลังหลักของสาขานั้นกลับเข้ามาในรายการให้เลือก
  • step ที่สองคือเลือก warehouse branch ที่จะเก็บลง storage
  • เมื่อเลือก warehouse แล้ว แอปจะ:
    • ล้าง tax cache
    • บันทึก branch ลง storage
    • แจ้ง navigator ว่า branch selection เสร็จแล้ว
    • พยายาม fetch tax data ต่อแบบ best effort

ตรวจ Firestore inventory index

  • กดค้างคลังใน step ที่ 2 เพื่อรัน real-time Firestore inventory query เดียวกับที่ product picker ใช้สำหรับคลังนั้น โดยจะไม่เลือกหรือเปลี่ยนคลังจากการกดค้าง
  • listener สำหรับตรวจสอบจะ log snapshot ที่ได้รับและหยุดเองภายใน 5 วินาที หากเริ่มตรวจคลังใหม่ ระบบจะหยุด listener เดิมก่อน
  • ถ้า Firestore ปฏิเสธ query เพราะยังไม่มี composite index, console จะแสดง [FIRESTORE CREATE INDEX] และ Firebase Console URL เป็นรายการแยก ทำให้ React Native DevTools เปิดเป็นลิงก์ที่กดได้

payload ที่บันทึกลง storage

branch ที่เลือกจะถูกเก็บเป็น JSON object เดียวใต้ key branch

shape ของข้อมูลคือ:

{
BranchId: string | number;
BranchCode: string;
whsGrpName: string;
whsGrpCode: string;
isMain: boolean;
}

ความหมายคือ:

  • BranchId คือ id ของ main branch ที่เลือก
  • BranchCode คือ code ของ main branch ที่เลือก
  • whsGrpCode คือ code ของคลังที่เลือกจริงใน step 2
  • whsGrpName คือชื่อคลังที่เลือก
  • isMain บอกว่าคลังที่เลือกเป็นคลังหลักของสาขานั้นหรือไม่

หมายเหตุเรื่องการใช้งานต่อ

  • หน้าจอและ service ที่ต้องใช้คลังที่เลือก มักอ่านจาก whsGrpCode
  • หน้าจอที่ต้องรู้ main branch owner code สามารถอ่านจาก BranchCode
  • TransferWarehouseDetail ตอนนี้ใช้ BranchCode ที่เก็บไว้เพื่อโหลด warehouse options ผ่าน getWarehousesSub(BranchCode) แต่ยังใช้ whsGrpCode ที่เก็บไว้เป็น source warehouse ของ flow สินค้าและ batch
  • ใน TransferWarehouseDetail ค่า company สำหรับโหลด Batch/Lot ต้องมาจากสินค้าที่เลือก (companyCode หรือ company) โดยตรง ไม่ใช้ company จากคลังปลายทาง; เมื่อเลือกสินค้าตัวแรก ระบบจะเติม companyCode และ companyName ของ header จาก company ของสินค้านั้น

ขั้นที่ 3 Home

  • เมื่อ auth และ branch ครบแล้ว RootNavigator จะ render Home
  • Home จะโหลด user และ branch จาก local storage
  • Home จะเช็ค login date ทุกครั้งที่ได้ focus; ถ้า login_date ที่เก็บไว้ไม่ใช่วันปัจจุบัน จะใช้ logout behavior เดิมของ mobile
  • Header ของ Home จะเช็ค required app update แบบเดียวกับหน้า Login รวมถึงตอนกลับมา focus ที่ Home
  • POS Terminal Home เช็ค required app update ซ้ำเมื่อกลับมา focus เช่นกัน
  • เมนูที่มองเห็นขึ้นกับ:
    • deptCode ของ user
    • ค่า isMain ของ branch ที่เลือก
  • เมนูจะพาผู้ใช้ไปยัง flow อื่นของ POS เช่น order, booking, invoice, shipping, stock, customer และ employee
  • การ logout จาก header จะล้าง session storage ทั้งหมดและพากลับไปสู่ login state

หมายเหตุ

  • session นี้มีอายุอิงตามวันที่ login ที่เก็บไว้
  • มี screen Branch อยู่ใน authenticated stack ด้วย ดังนั้นผู้ใช้สามารถกลับมาเลือก branch ใหม่หลังเข้า Home ได้
  • Home ทำหน้าที่ทั้งเป็น landing page และ permission gate ของ flow อื่นๆ