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

ใบจัดสินค้าสายส่งและขนส่ง

เอกสารนี้สรุป flow, action, status, API, เงื่อนไข และสิทธิ์ของ ใบจัดสินค้าสายส่ง และ ขนส่ง ตาม implementation ปัจจุบันของ Mobile และ POS Terminal

ขอบเขต

อ้างอิงจาก source หลัก:

  • apps/mobile/src/screens/shippingStack/shippingListScreen
  • apps/mobile/src/screens/shippingStack/shippingDetailScreen
  • apps/mobile/src/screens/transportStack/transportListScreen
  • apps/mobile/src/screens/transportStack/transportDetailScreen
  • apps/mobile/src/services/deliveries.ts
  • apps/mobile/src/services/transport.ts
  • apps/pos-terminal/src/screens/HomeScreen/ListPane.tsx
  • apps/pos-terminal/src/screens/HomeScreen/ShippingRouteDetailForm.tsx
  • apps/pos-terminal/src/screens/HomeScreen/TransportDetailForm.tsx
  • apps/pos-terminal/src/screens/HomeScreen/helpers.ts
  • apps/pos-terminal/src/services/splitMenuData.ts
  • apps/pos-terminal/src/services/transport.ts

Mobile และ POS Terminal ใช้ rule เดียวกันสำหรับ flow หลัก ถ้าระบุว่า “ทั้งสองฝั่ง” หมายถึง Mobile และ POS Terminal

คำศัพท์หลัก

คำความหมาย
ใบจัดสินค้าสายส่งเอกสาร delivery route ที่รวม invoice/order สำหรับสายส่ง
ขนส่งtransport trip ที่นำใบจัดหลายใบไปผูกกับทะเบียนรถและลูกค้า
เจ้าของใบจัดuserCode === detail.userCode
เจ้าของขนส่งuserCode === transport.userCode
ยืนยันใบจัดสายส่งการตั้ง confirmedAt ผ่าน PATCH /deliveries/{id}/confirm
รับงานใบจัดคลังรับงานผ่าน PATCH /deliveries/{id}/accept
อนุมัติใบจัดในขนส่งขนส่งตั้ง deliveryStatus = FINISHED ให้ใบจัดรายใบ

สถานะใบจัดสินค้าสายส่ง

Fieldค่าความหมายที่ UI ใช้
statusDELETEDเอกสารถูกลบ/ยกเลิก ไม่ให้ action หลัก
deliveryStatusnull, undefined, ''กำลังเตรียมใบจัด
deliveryStatusFINISHEDฝ่ายขายจัดใบสั่งขายเสร็จแล้ว หรือขนส่งอนุมัติใบจัดแล้ว
deliveryStatusCHECKLOCATIONคลังเช็คสินค้าแล้ว
deliveryStatusPENDING_FOR_B1รอ B1 ตัดสต๊อก
deliveryStatusSOME_DELIVERY_FAILมีข้อผิดพลาดในการตัดสต๊อก
deliveryStatusDONEตัดสต๊อกเรียบร้อย
loadingStatusemptyยังไม่ยืนยันการโหลดสินค้า
loadingStatusLOADING_DOCKจัดสินค้าไว้ที่ลานแล้ว
loadingStatusLOADEDจัดสินค้าขึ้นรถเรียบร้อย

รายการใบจัดสินค้าสายส่ง

หน้ารายการแสดงข้อมูลหลัก:

  • เลขที่ใบจัด: deliveryNo
  • วันที่สร้าง: createdAt
  • เส้นทาง: routeName
  • พนักงานขาย: createdBy
  • เวลา/สถานะยืนยันใบจัด:
    • ถ้า confirmedBy === "SYSTEM" แสดง (ข้อมูลเก่า {finishedAt})
    • ถ้า confirmedAt มีค่า แสดงเวลา confirmedAt
    • ถ้า confirmedAt เป็น '', null, หรือ undefined แสดง (ยังไม่ confirm)
  • พนักงานคลัง: acceptedByName
  • เวลารับงานคลัง: acceptedAt
  • พนักงานร่วมจัดสาย: grpDriverName

Icon เพิ่มเติม:

  • loadingStatus === "LOADING_DOCK" แสดง icon ลานโหลด
  • loadingStatus === "LOADED" แสดง icon รถ/โหลดขึ้นรถ
  • deliveryStatus === "DONE" แสดง icon check

Key ของรายการ:

  • Mobile ใช้ deliveryId เป็น key หลัก
  • Mobile fallback เป็น ${deliveryNo ?? 'shipping'}-${index}
  • POS Terminal ใช้ SplitListItem.id ที่ normalize จาก deliveryId
  • POS Terminal dedupe ด้วย deliveryId; ถ้าไม่มี ใช้ deliveryNo:{deliveryNo}

สิทธิ์เมนูใบจัดสายส่ง

เมนู ใบจัดส่งสินค้าสายส่ง แสดงเฉพาะ main branch และ MENU_SHIPPING.has(deptCode)

MENU_SHIPPING:

-2, 1, 2, 3, 4, 7, 29, 21, 8, 9, 12, 22, 27, 28, 13, 16, 14, 30

Shortcut สร้างใบจัดบน Mobile ใช้ CAN_CREATE_SHIPPING:

-2, 1, 2, 4, 7, 29, 21, 8, 9, 13, 16

สิทธิ์สร้าง/อนุมัติใบจัดใน helper ใช้ canFinalizeShippingSheet:

-2, 1, 2, 4, 7, 8, 9, 13, 16, 29, 30

Action ใบจัดสายส่ง

สร้างใบจัด

สร้างใบจัดด้วย invoice ที่เลือก:

POST /deliveries

payload เป็น array ของ invoice:

[
{ "invoiceId": 123 }
]

เพิ่ม invoice เข้าใบจัด

เพิ่ม invoice ได้เมื่อ:

  • ผู้ใช้เป็นเจ้าของใบจัด: userCode === detail.userCode
  • detail.status !== "DELETED"
  • confirmedAt ยังว่าง

เมื่อมี confirmedAt แล้ว ห้ามเพิ่ม/แก้ไข/จัดเรียง invoice

ลบ invoice ออกจากใบจัด

ลบ invoice ได้เมื่อ:

  • ผู้ใช้เป็นเจ้าของใบจัด: userCode === detail.userCode
  • detail.status !== "DELETED"
  • confirmedAt ยังว่าง
  • invoice นั้น toB1 !== 1

API:

DELETE /deliveries/{deliveryId}/invoices/{invoiceId}

จัดเรียง invoice

จัดเรียงได้เมื่อ:

  • ไม่ใช่ใบจัดที่ส่งเข้า transport แล้ว (toTransportation !== 1)
  • ยังแก้ไข invoice ได้ตาม rule เจ้าของเอกสารและ confirmedAt ยังว่าง

API:

POST /deliveries/{deliveryId}

payload:

[123, 456, 789]

ยืนยันใบจัดสายส่ง

ปุ่ม ยืนยันใบจัดสายส่ง แสดงใน header เมื่อ:

  • ผู้ใช้เป็นเจ้าของใบจัด
  • detail.status !== "DELETED"
  • confirmedAt ยังว่าง

ก่อนยืนยัน UI แสดง confirm alert:

หากยืนยันแล้ว จะไม่สามารถเพิ่ม แก้ไข หรือลบใบแจ้งหนี้ได้

API:

PATCH /deliveries/{deliveryId}/confirm

หลังสำเร็จ UI แจ้ง:

รอให้ขนส่งนำข้อมูลใบจัดเข้าขนส่ง และยืนยันใบ จึงจะดำเนินการต่อได้ หากต้องการแก้ไขใบจัดสายส่ง กรุณาให้คลัง เข้าไปปลดล็อคที่ขนส่ง

ผลของการ confirm:

  • backend ตั้ง confirmedAt, confirmedBy, confirmedByName
  • UI lock การเพิ่ม/แก้ไข/ลบ invoice
  • ขนส่งสามารถดึงใบจัดนี้ไปเลือกได้ เพราะ transport picker filter isConfirmed=1
  • งานคลังสามารถรับงานได้ถ้าเงื่อนไขรับงานครบ

รับงานใบจัด

ปุ่มรับงานแสดง/auto prompt เมื่อ:

  • confirmedAt มีค่า
  • toTransportation === 1 หรือ "1"
  • ยังไม่มี acceptedBy
  • user อยู่ใน dept รับงาน

Dept รับงาน:

12, 22, 28

API:

PATCH /deliveries/{deliveryId}/accept

ยืนยันสินค้าที่ลานและขึ้นรถ

Dept ที่ทำ dock/loading ได้:

8, 12, 22, 28, 29

Action:

  • ถ้ามี deliveryStatus แล้วและยังไม่มี loadingStatus แสดง ยืนยันการจัดสินค้าที่ลาน
  • เมื่อกด ส่ง loadingStatus = LOADING_DOCK
  • ถ้า loadingStatus === LOADING_DOCK แสดง ยืนยันการจัดสินค้าขึ้นรถสำเร็จ
  • เมื่อกด ส่ง loadingStatus = LOADED

API:

PATCH /deliveries/{deliveryId}/loading-dock

payload:

{ "loadingStatus": "LOADING_DOCK" }

หรือ:

{ "loadingStatus": "LOADED" }

ลงชื่อร่วมจัดสินค้า

ปุ่ม ลงชื่อร่วมจัดสินค้า แสดงเมื่อ:

  • loadingStatus === "LOADING_DOCK"
  • user อยู่ใน dept ลงชื่อร่วมจัด

Dept ลงชื่อร่วมจัด:

8, 12, 13, 14, 22, 28, 29, 30

API:

POST /deliveries/{deliveryId}/assign

payload:

{
"driverCode": "userCode",
"driverName": "ชื่อผู้ใช้"
}

ส่งข้อมูลไป B1 และแก้ lot

สิทธิ์ส่งไป B1:

2, 8, 12, 22, 28

แสดงเมื่อ:

  • detail.status !== "DELETED"
  • deliveryStatus เป็น CHECKLOCATION, PENDING_FOR_B1, หรือ SOME_DELIVERY_FAIL

ถ้า deliveryStatus เป็น PENDING_FOR_B1 หรือ SOME_DELIVERY_FAIL และมี invoice ที่ lot มีปัญหา UI แสดง action เลือก lot สินค้าที่มีปัญหาใหม่

ตรวจสินค้า

ตรวจสินค้าได้เมื่อ user เข้าเงื่อนไขใดเงื่อนไขหนึ่ง:

  • deptCode === 2
  • deptCode === 8
  • deptCode === 22
  • userCode === "999997"
  • acceptedBy ตรงกับ user ปัจจุบัน

ขอ cancel invoice

ทำได้เมื่อ:

  • deptCode อยู่ใน 12, 22, 28
  • detail.deliveryStatus !== "DONE"
  • invoice ไม่มีส่วนลด: discount <= 0
  • invoice ไม่ใช้ credit note: useCreditNote <= 0
  • invoice ยังไม่ส่ง B1: toB1 !== 1
  • มี invoiceId

ลบใบจัดจากหน้ารายการ

Mobile list และ POS list ใช้ rule ใกล้เคียงกัน:

  • ถ้า deliveryStatus เป็น null หรือ undefined: เจ้าของเอกสาร หรือ user ที่มี delDelivery === 1 ลบได้
  • ถ้า deliveryStatus === "FINISHED": deptCode === 16 หรือ admin หรือเจ้าของเอกสารลบได้
  • สถานะอื่นลบไม่ได้

สถานะขนส่ง

getTransportWorkflowStatus ใช้ค่า transportStatus หรือ status ก่อน ถ้าไม่มีจึง infer จาก timestamp:

สถานะขั้นตอนงานเงื่อนไข
emptyยังไม่มี transportNo
DRAFTมี transportNo, ยังไม่ prepare/start
PREPARINGเริ่มขนสินค้าขึ้นรถแล้ว
IN_PROGRESSมี startedAt
FINISHEDมี finishedAt
CANCELED / CANCELLED / CANCELถือว่ายกเลิก

Label ที่ UI ใช้:

StatusLabel
DRAFTเตรียมขนส่ง
PREPARINGกำลังขนสินค้าขึ้นรถ
IN_PROGRESSกำลังขนส่ง
FINISHEDขนส่งเสร็จสิ้น
canceledยกเลิก

สิทธิ์เมนูขนส่ง

เมนู ขนส่ง แสดงเฉพาะ main branch และ MENU_TRANSPORT.has(deptCode)

MENU_TRANSPORT:

-2, 1, 2, 3, 4, 7, 29, 21, 8, 9, 12, 13, 16, 14, 22, 27, 28, 30

Shortcut สร้างขนส่งบน Mobile ใช้ CAN_CREATE_TRANSPORT:

-2, 1, 2, 3, 4, 7, 29, 21, 8, 9, 13, 16, 14, 30

Action ขนส่ง

สร้าง/แก้ไขขนส่ง

สร้าง:

POST /transports

แก้ไข:

PATCH /transports/{transportId}

field สำคัญ:

  • branchId
  • shipDate
  • licensePlate
  • driverName
  • whGrpCode, whGrpName
  • userCode
  • routeCode, routeName
  • transportStatus
  • flagBank, flagGas
  • companyCode, companyName

Validation ขั้นต่ำ:

  • ต้องมีทะเบียนรถ
  • ต้องมีพนักงานขับรถ
  • ต้องมีวันที่ขนส่ง

ผู้แก้ไขขนส่งได้:

  • create mode: แก้ได้
  • detail mode: ต้องเป็นเจ้าของขนส่ง (userCode === transport.userCode)

เมื่อเริ่มงานแล้วหรือไม่ใช่ DRAFT step ข้อมูลหลักจะ lock

เลือกใบจัดเข้า transport

modal เลือกใบจัดเรียก:

GET /deliveries?page=1&pageLimit=32&sort=DESC&sortBy=CreatedAt&search={search}&branchId={branchId}&toTransportation=0&deliveryStatus=&status=ACTIVE&isConfirmed=1

เงื่อนไข:

  • transport ยังเป็น create mode หรือ DRAFT
  • ผู้ใช้แก้ไข transport ได้
  • ต้องเลือกทะเบียนรถแล้ว
  • ใบจัดต้องยังไม่ถูกผูกขนส่ง: toTransportation=0
  • ใบจัดต้อง active: status=ACTIVE
  • ใบจัดต้องยืนยันแล้ว: isConfirmed=1
  • modal ค้นหาได้ทั้ง Mobile และ POS Terminal

ก่อนเปิด dialog ยืนยันการเริ่มขนสินค้าขึ้นรถ ระบบใช้ GET /deliveries ชุดเดียวกัน แต่ส่ง search='' และเพิ่ม routeCode={transportPayload.routeCode} เพื่อหาใบจัดของเส้นทางเดียวกันที่ยังไม่ถูกผูกกับรอบขนส่ง

หลังเลือกใบจัด:

POST /transports/{transportId}/deliveries

payload:

{ "deliveryId": 123 }

ลบใบจัดออกจาก transport

ลบได้เมื่อ:

  • ผู้ใช้แก้ไข transport ได้
  • transport ยังเป็น DRAFT
  • ยังไม่ startedAt

API:

DELETE /transports/{transportId}/deliveries/{deliveryId}

อนุมัติใบจัดรายใบใน transport

ปุ่ม check รายใบแสดงเมื่อ:

  • ผู้ใช้แก้ไข transport ได้
  • transport เป็น DRAFT
  • transport ไม่ถูกยกเลิก
  • ใบจัดนั้น deliveryStatus เป็น pending

pending delivery status หมายถึง:

  • null
  • undefined
  • ''
  • whitespace
  • string "null" หรือ "NULL"

API:

PATCH /deliveries/{deliveryId}/status

payload:

{ "deliveryStatus": "FINISHED" }

อนุมัติใบจัดทั้งหมด

ปุ่มล่าง อนุมัติใบจัดทั้งหมด แสดงเมื่อ:

  • อยู่ step รายการใบจัด
  • user แก้ไข transport ได้ หรือเป็น override user code 999999
  • transport เป็น DRAFT
  • transport ไม่ถูกยกเลิก
  • มีใบจัดอย่างน้อย 1 ใบที่ยัง pending

เมื่อยืนยัน ระบบ loop ใบจัด pending ทุกใบ และเรียก API status เป็น FINISHED ทีละใบ

เริ่มขนสินค้าขึ้นรถ

ปุ่ม เริ่มขนสินค้าขึ้นรถ แสดงเมื่อ:

  • transport ไม่ใช่ create mode
  • user แก้ไข transport ได้ หรือเป็น override user code 999999
  • transport เป็น DRAFT
  • ใบจัดทุกใบมี deliveryStatus แล้ว
  • transport ไม่ถูกยกเลิก

API:

POST /transports/{transportId}/prepare

หากไม่พบใบจัดที่เข้าเกณฑ์ จะแสดง dialog ยืนยันเดิม หากพบ จะแจ้งว่าเส้นทางนั้นยังมีใบจัดที่ยังไม่ถูกนำเข้ารอบ และผู้ใช้ต้องยืนยันอีกครั้งก่อนส่ง POST /transports/{transportId}/prepare ผลคือ transport เข้าสถานะ PREPARING

ปลดล็อคขนสินค้าขึ้นรถ

เมื่อ transport เป็น PREPARING และไม่ถูกยกเลิก UI แสดง action unlock

ผู้กดต้องมี deptCode:

8, 12, 22, 28, 29, 4, 2

ถ้าไม่มีสิทธิ์ UI แจ้ง:

คุณไม่มีสิทธิ์ปลดล็อค

ก่อน submit ต้องกรอกหมายเหตุ ถ้าไม่กรอก UI แจ้ง:

กรุณาระบุหมายเหตุ

API:

PATCH /transports/{transportId}/cancel-prepare

payload:

{ "note": "เหตุผลการปลดล็อค" }

ผลคือปลดจาก PREPARING กลับมาให้แก้ไข/จัดการก่อนเริ่มขนส่งต่อ

เริ่มการขนส่ง

ปุ่ม เริ่มการขนส่ง ใช้ได้เมื่อ:

  • transport มี transportId
  • มีทะเบียนรถ
  • ใบจัดทุกใบมี deliveryStatus แล้ว
  • transport เป็น PREPARING
  • user แก้ไข transport ได้

ถ้าใบจัดยังไม่ครบสถานะ UI แจ้ง:

ใบจัดสายส่งทุกใบต้องถูกยืนยันก่อน จึงจะเริ่มขนส่งได้

ถ้ายังไม่ prepare UI แจ้ง:

กรุณาเริ่มขนสินค้าขึ้นรถก่อนเริ่มขนส่ง

API:

POST /transports/{transportId}/start

หรือ wrapper startTransport(...) ตาม payload ลูกค้า/พิกัด/ค่าขนส่งที่หน้าจอสร้างจากข้อมูล step ลูกค้า

รับชำระลูกค้า

ใน step ลูกค้า เมื่อเลือก action ชำระเงิน UI ใช้ payTransport

API:

POST /transports/{transportId}/pay

payload หลัก:

  • customerCode
  • paymentType
  • amount
  • cash
  • transfer
  • notes
  • U_BFP_Longitude, U_BFP_Latitude
  • currentLatitude, currentLongitude
  • signature
  • slipPath
  • shippingSlipPath
  • photo

ประเภท OTHER ต้องมี note, รูปส่งของ, และลายเซ็น ยกเว้น logic เฉพาะ transfer/bill payment ตามหน้าจอ

ก่อนเรียก payTransport หลักฐานจะถูกอัปโหลดแยกผ่าน:

POST /api/transports/{transportId}/files

body เป็น multipart/form-data ประกอบด้วย files, whGrpCode, customerCode, U_BFP_Latitude และ U_BFP_Longitude โดย 3 ฟิลด์หลังต้องมาจาก customer ที่กำลังเปิดอยู่และต้องมีค่าครบทุกครั้ง หากขาดฟิลด์ใด UI แจ้ง ไม่พบ customerCode หรือพิกัดลูกค้าสำหรับอัปโหลดไฟล์ และไม่เรียก upload API จากนั้นนำ path ที่ได้ไปใส่ใน photo, slipPath, shippingSlipPath หรือ signature ของ payment payload

เติมน้ำมัน

ใน step ลูกค้า footer มีรายการ เติมน้ำมัน

ถ้ายังไม่ completed และ user แก้ไข transport ได้:

  • เปิด modal จัดการเติมน้ำมัน
  • ปุ่ม เติมน้ำมัน เปิดฟอร์มบิลน้ำมัน
  • ปุ่ม ไม่เติมน้ำมัน update flagGas = 1

ฟอร์มบิลน้ำมันที่เปิดจากขนส่งจะตรวจ companyCode ก่อน submit โดยยอมรับเฉพาะ BFPDB, BFP, NFFDB และ NFF (ไม่สนตัวพิมพ์เล็ก/ใหญ่) เท่านั้น ค่าอื่น เช่น SSK จะถูกปฏิเสธก่อนเรียก API เพื่อไม่ให้ส่ง warehouse code เป็น company code

ขนส่งใหม่ตั้งต้น companyCode เป็น BFPDB เสมอ เมื่อผู้ใช้เลือกทะเบียนรถ ระบบใช้ companyCode จากข้อมูลรถที่เลือกมาแทนค่าในใบขนส่ง; หากรถไม่มีค่า company code จะคงค่าเดิมของใบขนส่งไว้

ก่อนจบ transport ถ้า flagGas === 0 UI แจ้ง:

คุณยังไม่จัดการเติมน้ำมัน

ฝากเงิน

ใน step ลูกค้า footer มีรายการ ฝากเงิน

ปัจจุบันซ่อนปุ่ม ฝากเงิน ไว้ แต่ comment โค้ดเดิมไว้เพื่อเปิดกลับได้ภายหลัง

เหลือ action ที่ใช้งาน:

  • ปุ่ม ไม่ฝากเงิน
  • เมื่อกด update flagBank = 1

ก่อนจบ transport ถ้า flagBank === 0 UI แจ้ง:

คุณยังไม่จัดการฝากเงิน

สิ้นสุดการขนส่ง

ปุ่ม สิ้นสุดการขนส่ง แสดงเมื่อ:

  • transport มี startedAt
  • ยังไม่มี finishedAt
  • user แก้ไข transport ได้

ก่อนจบต้องผ่าน guard:

  • จำนวนงานที่ส่งเสร็จต้องครบ: totalFinished === total
  • flagBank !== 0
  • flagGas !== 0
  • เลขไมล์สิ้นสุดต้องถูกต้อง
  • เลขไมล์สิ้นสุดต้องมากกว่าเลขไมล์เดิม
  • ถ้ามี mileage balance ห้ามเกินกำหนด

API:

PATCH /transports/{transportId}/finish

หลังสำเร็จ UI refresh แล้วกลับไปหน้า TransportList

ลบ transport จากรายการ

ลบ transport ได้เมื่อ:

  • transport เป็น DRAFT
  • เจ้าของ transport ตรงกับ user ปัจจุบัน

ถ้าไม่มี transportStatus จะถือว่า draft เมื่อยังไม่มี startedAt

รายการ API สำคัญ

การจัดส่ง

ActionMethod และ path
สร้างใบจัดPOST /deliveries
รายละเอียดใบจัดGET /deliveries/{id}
ลบใบจัดDELETE /deliveries/{id}
ยืนยันใบจัดPATCH /deliveries/{id}/confirm
รับงานใบจัดPATCH /deliveries/{id}/accept
update deliveryStatusPATCH /deliveries/{id}/status
update loadingStatusPATCH /deliveries/{id}/loading-dock
จัดเรียง invoicePOST /deliveries/{id}
ลบ invoice จากใบจัดDELETE /deliveries/{id}/invoices/{invoiceId}
ลงชื่อร่วมจัดPOST /deliveries/{id}/assign
บันทึก lotPOST /deliveries/{id}/lots

ขนส่ง

ActionMethod และ path
รายการขนส่งGET /transports
รายละเอียดขนส่งGET /transports/{id}
สร้างขนส่งPOST /transports
แก้ไขขนส่งPATCH /transports/{id}
เลือกใบจัดเข้า transportPOST /transports/{id}/deliveries
ลบใบจัดออกจาก transportDELETE /transports/{id}/deliveries/{deliveryId}
เริ่มขนสินค้าขึ้นรถPATCH /transports/{id}/prepare
ปลดล็อค preparePATCH /transports/{id}/cancel-prepare
เริ่มขนส่งPOST /transports/{id}/start
รับชำระPOST /transports/{id}/pay
จบขนส่งPATCH /transports/{id}/finish
invoice ทั้งหมดของ transportGET /transports/{id}/invoices

Parity ระหว่าง Mobile และ POS Terminal

สิ่งที่ต้องคงให้ตรงกัน:

  • list card ใบจัดสายส่งใช้ confirmedAt สำหรับเวลายืนยัน
  • ถ้า confirmedBy === "SYSTEM" แสดง (ข้อมูลเก่า {finishedAt})
  • ถ้าไม่มี confirmedAt แสดง (ยังไม่ confirm)
  • รับงานใบจัดต้องใช้ confirmedAt มีค่า ไม่ใช่ confirmedAt ว่าง
  • modal เลือกใบจัดในขนส่งต้องส่ง isConfirmed=1
  • modal เลือกใบจัดในขนส่งต้องค้นหาได้
  • ปุ่มฝากเงินใน transport ถูกซ่อน เหลือ ไม่ฝากเงิน
  • ปุ่ม unlock prepare ใช้ deptCode ชุดเดียวกัน

Checklist การดูแล

เมื่อแก้ flow นี้ให้ตรวจ:

  1. Mobile shipping helper และ POS helper ให้ rule เท่ากัน
  2. Mobile transport detail และ POS TransportDetailForm ให้ action/guard เท่ากัน
  3. service path ใน deliveries.ts, transport.ts, และ splitMenuData.ts
  4. list card ของ Mobile และ POS Terminal
  5. wiki หน้านี้ และ changelog ถ้าเปลี่ยน behavior ที่ผู้ใช้เห็น