ใบจัดส่งสินค้าหน้าร้าน
เมนูนี้ใช้จัดการใบแจ้งหนี้ที่ต้องเตรียมสินค้าและส่งมอบที่สาขา/หน้าร้าน ไม่ใช่หน้าขาย POS และไม่ใช่ใบจัดสินค้าสายส่ง หน่วยงานที่ผู้ใช้เห็นบนหน้าจอเปลี่ยนเป็น ใบสั่งขาย (orderNo) ส่วนการรับงาน บันทึก Lot/Batch สร้าง delivery และตัดสต๊อก B1 ยังคงเรียก API แยกทีละ Invoice
จุดเข้าใช้งาน
| แอป | หน้าจอ |
|---|---|
| Mobile | StorefrontListScreen -> StorefrontDetailScreen |
| POS Terminal | shippingStorefront -> StorefrontDetailForm ใน HomeScreen |
เมนูนี้แสดงข้อมูลอะไร
รายการมาจากใบแจ้งหนี้ที่มี shippingType = 2 ระบบตัดรายการที่ invoiceStatus = CANCELED ออกทั้งหมดก่อน Group จากนั้น dedupe และ Group รายการที่เหลือด้วย orderNo หากไม่มีเลขใบสั่งขายจึง fallback เป็น key ระดับ Invoice
แต่ละการ์ดแสดงชื่อลูกค้า เลขใบสั่งขาย เลขใบเบิกทุกใบแยกคนละบรรทัด พนักงานขาย และพนักงานคลัง ส่วนแท็บ NEW จะประเมินจากทั้ง Group โดย Group จะยังเป็น NEW จนกว่า Invoice ทุกใบจะเป็น CONFIRMED
สีพื้นหลังของการ์ด Group
ระบบประเมินสีหลังตัด Invoice ที่ยกเลิกออกแล้ว ตามลำดับดังนี้:
| เงื่อนไขของ Group | สีพื้นหลัง |
|---|---|
Invoice ทุกใบเป็น CONFIRMED | เขียว #76ffa3 |
มี Invoice ใดเป็น NEW และ hasDelivery != null | ม่วง #d382ff |
มี Invoice ใดมีคำขอยกเลิกค้างอยู่ (canceledNote != null และ rejectCanceledAt == null) | ม่วงอ่อน #e7bce7 |
| Group ผสม/ยังไม่ยืนยันกรณีอื่น | เขียวอมเหลือง #cffd67 |
เมื่อกดการ์ด ระบบส่ง Invoice ID ทุกใบพร้อม orderNo เข้าหน้ารายละเอียด แล้วโหลดทุก Invoice ด้วย includeLot=true มารวมในหน้าเดียว รายการสินค้าแต่ละบรรทัดยังเก็บ sourceInvoiceId, sourceInvoiceNo, sourceInvoiceStatus และผู้รับงานของ Invoice ต้นทาง เพื่อให้ validation และ API ยังคงแยกตาม Invoice ได้
Flow หลัก
เงื่อนไขการรับงาน
| เงื่อนไข | พฤติกรรม |
|---|---|
| สาขาหลัก | ผู้ใช้ในแผนกที่รับงานได้จะถูกถามให้รับงานเมื่อ acceptedBy ยังว่าง |
| สาขาย่อย | เปิด accept flow เช่นกัน แต่การแก้ไข Lot/Batch ใช้สิทธิ์เดียวกับสาขาหลักและไม่ขึ้นกับ isMain |
| ทุก Invoice รับงานไปแล้ว | ไม่ถามซ้ำ |
| มีทั้งใบที่รับและยังไม่รับงาน | แสดง Modal ครั้งเดียว เมื่อยืนยันจะเรียก Accept API ทีละใบ เฉพาะ Invoice ที่ acceptedBy ยังว่าง ใบที่รับงานแล้วจะไม่ยิงซ้ำ |
| ผู้ใช้ที่รับงาน | แก้และบันทึกงานต่อได้ |
| ผู้ใช้ override | user code 999997 ถือเป็นผู้มีสิทธิ์ action |
สิทธิ์รับงานใช้แผนก 8, 12, 22, 28
เงื่อนไขการตรวจสินค้าและ Lot/Batch
กฎสำคัญของรายการสินค้า:
| กฎ | พฤติกรรม |
|---|---|
| สถานะที่แก้ได้ | แก้การตรวจสินค้าได้เฉพาะเมื่อ Invoice ต้นทางเป็น NEW; สินค้าของ Invoice ที่ CONFIRMED ยังแสดงแต่เปิดตัวเลือก Lot/Batch ไม่ได้ |
| Lot เดิมจาก invoice | หาก items[].lots[] จาก GET /invoices/{id}?includeLot=true มีข้อมูลที่ใช้ได้ ระบบแสดงเป็นค่าเริ่มต้น และผู้ใช้ยังแก้จำนวน ลบ หรือเลือก Lot/Batch ใหม่ได้ เมื่อเอกสารเป็น NEW และมีสิทธิ์แก้ไข |
| การเลือก lot | กดครั้งแรกหลังโหลดรายละเอียดจะคำนวณจากจำนวนเต็มของบรรทัด แม้มี Lot เดิมแสดงอยู่แล้ว โดยใช้ Lot เดิมก่อนแล้วเติมส่วนที่ขาดตามลำดับวันหมดอายุจาก API เมื่อกดซ้ำจะเปิดแก้ไขรายการปัจจุบันโดยไม่ใส่ Lot เดิมทับการแก้ไข |
isMain | ไม่ใช้เป็นเงื่อนไขล็อกหรือจำกัดการเลือก Lot/Batch การแก้ไขใช้กติกาเดียวกันทั้งสาขาหลักและสาขาย่อย |
| ยอดคงเหลือ | โหลดรวม Lot ที่ available เป็น 0 เพื่อคืนยอดจอง โดยคืนเฉพาะ Lot ของบรรทัดและ Invoice นี้ที่สินค้า/บริษัท/คลังตรงกัน ไม่เกิน booking และ stock จริงที่ API ระบุ หาก Batch เดิมหายจาก API จะเพิ่มตัวเลือกด้วยยอดจองและวันที่ของ Lot เดิม การคืนยอดนี้ใช้คำนวณในหน้าจอเท่านั้น |
| จำนวนไม่พอ | ตอนกดครั้งแรก ถ้ายอดรวมหลังคืนจองน้อยกว่าจำนวนเต็มของบรรทัด รวมถึงกรณีไม่มี stock จะแสดง error ระบุจำนวนต้องการ/มีให้เลือก/ขาด ก่อนเปลี่ยนรายการหรือเปิด Modal ส่วนการโหลดใหม่ในตัวเลือกแบบ manual ยังแสดงข้อความไม่พบข้อมูลพร้อมปุ่มโหลดใหม่เมื่อไม่มี Lot |
| ข้อมูลสินค้าที่ต้องมี | ต้องมี itemCode, whsCode, company ก่อนโหลด lot |
| lot ซ้ำ | สินค้าหนึ่งบรรทัดเลือก Lot/Batch เดิมซ้ำไม่ได้ |
| จำนวนคงเหลือ lot | จำนวนที่กรอกต้องไม่เกินยอดคงเหลือของ lot นั้น |
| จำนวนตาม invoice line | จำนวนที่กรอกต้องไม่เกินจำนวนค้างตรวจของบรรทัดนั้น |
| การตรวจครบ | ต้องตรวจครบทุกบรรทัดก่อนบันทึก |
| เลือกอัตโนมัติ | เมื่อใช้ยอดจองเดิมแล้วเลือกครบ และตัวเลือกทั้งหมดที่มียอดบวกมีไม่เกิน 2 Batch ที่ไม่ซ้ำกัน จะไม่เปิด Modal; หากเกิน 2 Batch จะเปิดให้ตรวจแก้ ถ้าไม่มีจองเดิมให้ใช้ จะเลือกอัตโนมัติเฉพาะกรณีมี Lot เดียวเพียงพอ ส่วนหลาย Lot ยังเลือกเอง |
ตัวอย่าง ต้องการ 9 ชิ้น มีจองเดิม 8 ชิ้นที่ 260812-NMA8033 และ API มี 260812-NMA8034 ว่าง 15 ชิ้น ระบบเลือก Batch เดิม 8 และ Batch ใหม่ 1 ชิ้น หากมีตัวเลือกเพียงสอง Batch นี้จะไม่เปิด Modal และไม่นำยอดจองของ Invoice หรือบรรทัดอื่นมาคืนให้บรรทัดนี้
Mobile และ POS Terminal ใช้ packages/utils/src/storefrontLots.ts ร่วมกัน โดยใช้ตัวคืนยอดจองและจัดสรรเดียวกับสายส่ง การเลือกไม่เรียก API ปลดจอง และยังใช้สัญญาการบันทึกแยก Invoice ตามหัวข้อด้านล่าง
เงื่อนไขการบันทึก Delivery / B1
ปุ่มบันทึกจะแสดงเมื่อใน Group มีอย่างน้อยหนึ่ง Invoice ที่ไม่ใช่ CONFIRMED/CANCELED และผู้ใช้มีสิทธิ์ action สำหรับใบนั้น ส่วน Invoice ที่ CONFIRMED แล้วจะแสดงแบบอ่านอย่างเดียวและไม่ถูกส่งซ้ำ
ก่อนบันทึก ระบบจะบล็อกกรณีต่อไปนี้:
| Guard | กรณีที่บล็อก |
|---|---|
| สิทธิ์ | ผู้ใช้ไม่มีสิทธิ์บันทึกข้อมูลหน้าร้าน |
| SAP reference | ไม่มี refKey แปลว่า invoice ยังไม่มีข้อมูล SAP/B1 |
| มีคำขอยกเลิก | มี canceledAt และยังไม่มี rejectCanceledAt |
| ตรวจสินค้าไม่ครบ | จำนวนตรวจของบางรายการยังน้อยกว่าจำนวนตาม invoice |
ระบบ Validate Invoice ที่ยังไม่ยืนยันทีละใบ โดยตรวจเฉพาะรายการสินค้าของ Invoice นั้น เมื่อทุกใบผ่านแล้ว Mobile และ POS Terminal จะวนทำงานตามลำดับทีละ Invoice:
- ข้าม Invoice ที่เป็น
CONFIRMED - เพิ่ม Invoice ปัจจุบันเข้า delivery
0หากยังไม่มีdeliveryId - สร้าง payload
invoices[].items[].lots[]จากรายการสินค้าของ Invoice ปัจจุบันเท่านั้น - บันทึก delivery lots ของ Invoice ปัจจุบัน
- สร้าง delivery/ส่งตัดสต๊อกของ Invoice ปัจจุบัน
- ทำ Invoice ถัดไป แล้วจึงโหลดรายละเอียด Group และรายการใหม่เมื่อครบทุกใบ
Metadata ในรายละเอียดแบบ Group
| ข้อมูล | การแสดงผล |
|---|---|
| ลูกค้า | ชื่อลูกค้าร่วมของใบสั่งขาย |
| ใบสั่งขาย | orderNo |
| ใบเบิก | แสดง invoiceNo ทุกใบต่อกันด้วย , |
| รายการสินค้า | รวมสินค้าจากทุก Invoice ใน Group |
| สินค้าของใบที่ยืนยันแล้ว | แสดงเป็นรายการที่เสร็จ/อ่านอย่างเดียว และปิดการเลือก Lot/Batch |
เงื่อนไขการแจ้งยกเลิก
การยกเลิกเป็นการส่งคำขอพร้อมเหตุผล ไม่ใช่การลบประวัติ Invoice ในรายละเอียดแบบ Group ระบบตรวจ guard จากทั้ง Group และส่งคำขอยกเลิกทีละใบเฉพาะ Invoice ที่ยังไม่ CONFIRMED ส่วนการพิมพ์ใบแจ้งหนี้จะพิมพ์ Invoice ทุกใบใน Group ทีละใบ
สิทธิ์และ Guard
| หัวข้อ | พฤติกรรม |
|---|---|
| Terminal menu key | shippingStorefront |
| deptCode ที่เห็นเมนู | -2, 1, 2, 3, 4, 7, 29, 21, 8, 9, 12, 20, 22, 23, 27, 28 |
| แผนกรับงาน | 8, 12, 22, 28 |
| แผนกบันทึก/action | 2, 8, 22 หรือผู้ใช้ที่รับงาน หรือ override user 999997 |
| สถานะ Invoice ที่แก้ได้ | Invoice ต้นทางเป็น NEW เท่านั้น |
| สถานะที่ซ่อนปุ่มบันทึก | CONFIRMED, CANCELED, หรือไม่มีสิทธิ์ action |
Mobile vs POS Terminal
| หัวข้อ | Mobile | POS Terminal |
|---|---|---|
| การนำทาง | storefront stack แบบเต็มหน้าจอ | HomeScreen split-pane |
| รับงาน | prompt ในหน้ารายละเอียด | prompt ใน detail form |
| เลือก Lot/Batch | bottom sheet และ modal | modal/picker ใน split-pane |
| การบันทึก | บันทึก delivery lots + create delivery | ใช้ service flow เดียวกัน |
| ยกเลิก | modal กรอกเหตุผล | modal กรอกเหตุผล |
Developer Handoff Map
| ส่วน | โค้ด |
|---|---|
| Mobile list/detail | apps/mobile/src/screens/storefrontStack/storefrontListScreen, storefrontDetailScreen |
| Mobile helpers | apps/mobile/src/screens/storefrontStack/storefrontDetailScreen/helpers.ts |
| Terminal split data | apps/pos-terminal/src/services/splitMenuData.ts -> shippingStorefront |
| Terminal detail | apps/pos-terminal/src/screens/HomeScreen/StorefrontDetailForm.tsx |
| Terminal rules | apps/pos-terminal/src/screens/HomeScreen/StorefrontDetailHelpers.ts |
| Storefront service | apps/*/src/services/storefront.ts |
| Delivery/lot service | apps/*/src/services/shipping.ts |
การแจ้งยกเลิกจากหน้านี้เป็นการส่งคำขอให้พิจารณาที่ เมนูใบแจ้งหนี้ ส่วนใบที่มี hasDelivery = null และผ่านเงื่อนไข สามารถยกเลิกโดยไม่มีคำขอจากหน้ารายการใบแจ้งหนี้ได้ ดูสิทธิ์เจ้าของ/แอดมิน การบังคับกรอก notes และ Sweet Alert global ในเอกสารดังกล่าว