ภาพรวม
DateBox/NumberBox เป็น widget กลางที่ทุกหน้าจอใช้ แก้ผิดที่เดียวพังทั้งระบบ ช่วง 22-24 ต.ค. 2026 เจอ 4 กลุ่ม: วันที่ที่พิมพ์ (slash หาย/วันที่เป็นไปไม่ได้ผ่าน), ปุ่มแรกหลัง focus หาย, ตัวเลขกึ่งสำเร็จ (5., .5, 100+7%) เพี้ยน, และค่า 0 ที่ต้องว่างแต่ DB ส่ง string '0.00' ซึ่ง truthy ใน JS ทุกเคสแก้ที่ widget/helper กลาง ไม่แก้ทีละหน้าจอ
อาการ
- A) พิมพ์
1/2/2569slash ถูกกิน;31/02/2026ช่องรับค่าทั้งที่ไม่มีวันนั้น - B) UAT NB-1/M-3/OBS-LOOKUP-FASTTYPE: พิมพ์เร็วหลัง focus
123456ได้23,456,1122-00ได้122-00 - C)
100+7%ได้ 100.07 (ควร 107);"30.00"ในช่องจำนวนเต็มกลายเป็น"300"; วาง/พิมพ์.5/5.ถูกปฏิเสธหรือ caret กระโดด (N1-N4) - D) ช่องราคา 0 โชว์
0.00ทั้งที่กติกาตาม C# คือเว้นว่าง
สาเหตุ (root cause)
- A) ฟอร์แมตระหว่างพิมพ์ไม่รู้ว่า slash มาจากผู้ใช้ และ
dmyToIsoไม่ตรวจว่าวันที่มีจริง (diff82dbe5d4ตรวจแล้ว) - B) select-all หลัง focus ใช้
requestAnimationFrameจึงช้ากว่า keystroke แรก ปุ่มแรกถูก select ทับ; อีกชั้น draft ถูก resync จากค่าที่ backend เติมระหว่างผู้ใช้กำลังพิมพ์ (NUMBERBOX-RESYNC) - C) (diff
faa6e6d0ตรวจแล้ว) ช่องไม่รับทศนิยมลบจุดแล้วเอาเลขมาต่อ แทนตัดส่วนหลังจุด;decimalSqlไม่รับ.5/5.ที่ NumberBox เก็บตามที่พิมพ์;%ถูกตีเป็นเศษส่วนแทน "บวก 7% ของ 100"; caret นับบนข้อความที่มี comma (1,234) - D)
848b9e05เขียนx ? x : ""แต่ DB ให้'0.00'(truthy) จึงไม่ว่าง ต้องแก้ซ้ำใน309f9986เป็นNumber(x) ? x : ""บั๊กเดิมพลาดสองรอบ
วิธีแก้
- A)
82dbe5d4:formatDateTypingเก็บ slash ที่ผู้ใช้พิมพ์ไม่เติมซ้ำ;dmyToIsoคืนnullเมื่อวันที่เป็นไปไม่ได้; blur ผิดเตือน "ป้อนวันที่ผิดพลาด" แล้วล้างช่อง (DATEBOX-INVALID-BLUR).65344f12พอร์ต_myDateBox._checkDateของ C#: ตัวคั่น' ' '-' '.' '*'=/, ส่วนที่ขาดเอาจากวันที่ทำงาน, รับ ddmm/ddmmyy, ปี 2 หลัก = 20yy (มติ R3g SHAREDUI).5fa7e098ปรับให้รู้year_type: พ.ศ. = 2500+yy - B)
82dbe5d4: select-all เป็นuseLayoutEffectแบบ synchronous;useFocusDraftมี flagtyped+seenValue/selectEpochพิมพ์แล้วห้ามทับ draft ด้วยค่า programmatic - C)
faa6e6d0: ตัดส่วนหลังจุด,decimalSqlnormalize.5/5.ก่อนตรวจ,100+7%=107, วางข้อความใช้input.value, blur เรียกfinishNumber()(5.->5,.5->0.5,-->0) commit นี้รวมแก้ security หลายข้อด้วย - D)
309f9986แก้เป็นNumber(x) ? x : "";4758d54aเปลี่ยน input ธรรมดาใน SerialStockCountScreen/TransTopForm เป็นNumberBoxและเก็บราคา 0 เป็น""
commit ที่เกี่ยวข้อง
82dbe5d4 (DateBox, select-all, RESYNC), 65344f12 (completeDmy), 5fa7e098 (ปี 2 หลักตาม year_type), faa6e6d0 (N1-N4, N5 invalidateSmlSettings, N6 formatThaiDate), 848b9e05 -> 309f9986 (blank-zero), 4758d54a (input -> NumberBox)
โค้ดปัจจุบันที่ป้องกัน
frontend/shared/ui/dateText.ts:30,51,71(dmyToIso,completeDmy,formatDateTyping; ปี 2 หลัก:61-62); เทสต์frontend/shared/ui/dateText.test.tsfrontend/shared/ui/DateBox.tsx:132(alert + ล้างเมื่อ blur ผิด)frontend/shared/ui/useSelectAllOnFocus.ts:20(useLayoutEffectselect ทันที)frontend/shared/ui/NumberBox.tsx:27,31,63,66(useFocusDraft,typed,isUnfinishedNumber,finishNumber)frontend/src/lib/numeric.ts:110,553,842(decimalSql,isZeroDecimal,evalArithmeticSafe); เทสต์numeric.test.ts:115,144- รูปแบบที่ถูก:
frontend/account/pos/PosSetupAndControlScreen.tsx:1431(Number(x) ? x : "")
บทเรียน / กฎที่ได้
- ค่าตัวเลขจาก DB เป็น string (
'0.00') ห้ามเช็ก truthiness ใช้Number(x)หรือisZeroDecimal - ช่องตัวเลข/วันที่ใช้
NumberBox/DateBoxเท่านั้น ห้าม<input>ธรรมดา - select-all ต้อง synchronous ก่อน keystroke แรก และห้าม resync draft ทับสิ่งที่ผู้ใช้เพิ่งพิมพ์
- ปฏิเสธวันที่เป็นไปไม่ได้ที่ชั้นแปลง (
dmyToIso=null) ไม่ใช่รอ SQL ล้ม - แก้บั๊กรูปแบบเดียวกันต้อง grep ทุกจุดที่ใช้ pattern เดิม (blank-zero พลาดสองรอบ)
- ยังไม่ได้ตรวจ diff
4758d54aครบทุกไฟล์ (ตรวจเฉพาะส่วน input -> NumberBox และ blank-zero)
ดูเพิ่ม
บทเรียน ปี พ.ศ./ค.ศ. และวันที่ (Dates, Buddhist year and year_type) · บทเรียนบั๊กการปัดเศษและทศนิยมเงิน (Rounding & Decimal Bugs) · ช่องกรอกมาตรฐานและกฎป้ายข้อความ (NumberBox, DateBox, CodeBox, LookupBox, ห้าม F1-F12) · ตัวเลข เงิน ภาษี และปี พ.ศ. ฝั่ง frontend (numeric.ts) · การปัดเศษ ทศนิยม และตัวเลขเงิน (Rounding & Decimal Policy) · บทเรียนบั๊ก UX/หน้าจอธุรกรรม/Master/แท็บ MDI (Frontend UX Bug Lessons) · history-overview
ที่มาในโค้ด
repo smlaiaccount (อ่านอย่างเดียว): frontend/shared/ui/{dateText.ts,DateBox.tsx,NumberBox.tsx,useSelectAllOnFocus.ts}, frontend/src/lib/numeric.ts, AGENTS.md:40-41, diff ของ 82dbe5d4, 65344f12, faa6e6d0, 848b9e05, 309f9986, 4758d54a, 5fa7e098