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

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

เอกสารนี้สรุป 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 สินค้าที่มีปัญหาใหม่

คืนยอด Lot เดิมและเลือกใหม่​

ทั้ง Mobile และ POS Terminal ใช้ restoreShippingLotOptions / buildShippingLotSelection ร่วมกัน: คืนสิทธิจาก invoices[].products[].lots เฉพาะ Invoice ที่กำลังแก้ ใช้ Lot เดิมก่อน และเติมส่วนที่ขาดจาก Lot ใหม่ รองรับ Lot เดิมที่ API ไม่ส่งกลับ โดยไม่เพิ่มสต๊อกจริงบน server

  • หลังคืนยอดแล้วจำนวนรวมไม่พอ: แจ้ง error ทันที ไม่เลือกบางส่วนและไม่เปิด Batch Modal
  • มียอดจองเดิมให้ใช้และเลือกครบ โดยตัวเลือกที่รวมแล้วมี batchNumber ไม่ซ้ำไม่เกิน 2: เลือกให้โดยไม่เปิด Modal
  • ตัวเลือกที่รวมแล้วเกิน 2 Batch: เปิดตัวแก้ไขให้ตรวจสอบ แม้ยอดที่จัดสรรจริงใช้ไม่เกิน 2 Batch
  • ไม่มีสิทธิยอดจองเดิม: คง flow Lot เดียวอัตโนมัติ / หลาย Lot เลือกเอง

ดูสูตร เพดานยอดจอง วันที่ Lot ที่หายไป debug log และ QA ใน การเลือก 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 ที่ผู้ใช้เห็น