Login ไป Branch ไป Home
หน้านี้อธิบาย mobile startup flow ปัจจุบันจาก implementation จริงใน apps/mobile
อ้างอิงจากโค้ด
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
ลำดับการตัดสินใจตอนเริ่มแอป
ขั้นที่ 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/androidVersioniosVersionNumber/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 code999999userBranchesจาก 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 2whsGrpNameคือชื่อคลังที่เลือก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จะ renderHome - 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
Navigation states ใน RootNavigator
หมายเหตุ
- session นี้มีอายุอิงตามวันที่ login ที่เก็บไว้
- มี screen
Branchอยู่ใน authenticated stack ด้วย ดังนั้นผู้ใช้สามารถกลับมาเลือก branch ใหม่หลังเข้า Home ได้ - Home ทำหน้าที่ทั้งเป็น landing page และ permission gate ของ flow อื่นๆ