สมอง SML

คลังความรู้ / หน้าจอทีละจอ

#screens#report

รายละเอียดการซื้อ/การขาย 4 ช่อง (BuySaleInformationScreen)

หน้าจอวิเคราะห์ "ลูกค้า/เจ้าหนี้รายหนึ่งซื้อหรือขายอะไรไปบ้าง" แบ่งเป็น 4 ช่อง (quadrant) ในจอเดียว ใช้คอมโพเนนต์เดียวกัน 2 โหมด: ขาย (mode="sale") และซื้อ (mode="buy") (BuySaleInformationScreen.tsx:27-40) หัวไฟล์อ้างว่าพอร์ตมาจากหน้าจอ C# SMLERPICInfo._buyAndSaleInformation (บรรทัด 1-10 ของไฟล์) ต่างจากรายงานอื่นที่เป็นตระกูล จอรายงานกลาง (Universal Report Screen) ตรงที่หน้าจอนี้ ไม่ผ่าน backend report engine แต่ยิง SQL จากเบราว์เซอร์ผ่าน queryList (ดู ตัวเรียก API และตัวประกอบ SQL ฝั่งเบราว์เซอร์ (api-client, query-client, sml-query-builder))

วิธีเปิด (และข้อควรระวังเรื่องเมนู)

  • registry มี 2 คีย์ที่ชี้มาที่จอนี้: menu_po_buy_information (รหัสเก่า 3.8.7 ชื่อ "รายละเอียดการซื้อ") และ menu_so_sale_information (รหัสเก่า 4.10.22 ชื่อ "รายละเอียดการขาย") เปิดเป็นแท็บ (mode: "tab") (screenRegistry.tsx:741-765)
  • แต่ใน smlMenu.json ปัจจุบัน ไม่มีเมนูใบที่ชื่อสองคีย์นี้ — smlMenu.ts ทำ alias ให้สองชื่อนี้ชี้ไปที่ menu_po_report_purchase (3049 "รายงานการซื้อสินค้า/ตั้งหนี้") และ menu_so_report_invoice (4045 "รายงานการขายสินค้าและบริการ") (smlMenu.ts:212-213) ซึ่งทั้งสองเมนูเป็นใบประเภท RPT เปิดด้วย UniversalReportScreen (จอรายงานกลาง (UniversalReportScreen)) ไม่ใช่จอนี้
  • ผลคือในเมนูปัจจุบันไม่พบทางเปิดจอ 4 ช่องนี้โดยตรง ค้นทั้ง frontend/ (ไม่รวม .next/) ไม่พบโค้ดอื่นที่เปิดสองคีย์นี้ นอกจาก registry เอง ถือเป็น จอที่ลงทะเบียนไว้แต่ไม่มีเมนูชี้ (ดูตารางความไม่สอดคล้องใน สารบัญหน้าจอทั้งหมดของ SML Ai Account (ต้นไม้เมนู → หน้าจอ → โน้ต))

หน้าตาและการทำงาน

หัวจอเขียนว่า "หน้าจอวิเคราะห์ข้อมูลการขายและลูกหนี้" หรือ "…การซื้อและเจ้าหนี้" พร้อมรหัสลูกค้า — ชื่อที่เลือกอยู่ (บรรทัด 204-207) แถบเครื่องมือมีปุ่ม "ประมวลผลใหม่" (โหลดรายชื่อใหม่) และ "ปิดหน้าจอ" (แสดงเมื่อมี onClose) (บรรทัด 213-217) ตามด้วยรหัสเมนูและชื่อจอ

ช่องซ้ายบน: รายชื่อลูกหนี้ / เจ้าหนี้

  • ช่องค้นหา "ค้นหารหัส/ชื่อลูกหนี้..." (หรือ "…เจ้าหนี้...") ใช้ ILIKE กับ code และ name_1 โดย escape อักขระ % _ \ ให้เป็นตัวอักษรธรรมดา และผ่าน escapeSql (บรรทัด 63-69) กด Enter หรือปุ่มแว่นขยายได้
  • ช็อกบ็อกซ์ "เฉพาะมียอดซื้อ/ขาย" กรองใน SQL ก่อน LIMIT (บรรทัด 74, 259) เพื่อไม่ให้รายการที่มียอดหล่นหายไปนอก 100 แถวแรก
  • ตารางคอลัมน์ รหัส / ชื่อลูกหนี้ (ชื่อเจ้าหนี้) / ยอดขายสะสม (ยอดซื้อสะสม) (บรรทัด 271) ดึงเฉพาะผู้ที่ COALESCE(status,0)=0 เรียงตามรหัส สูงสุด 100 แถว (บรรทัด 76-82) คลิกแถวเพื่อเลือก ครั้งแรกที่โหลดเสร็จจะเลือกแถวแรกให้เอง (บรรทัด 93-97)
  • ตารางต้นทาง: ลูกหนี้ ทะเบียนลูกหนี้/ลูกค้า (ar_customer) / เจ้าหนี้ ทะเบียนเจ้าหนี้/ผู้ขาย (ap_supplier)

ช่องซ้ายล่าง: สรุปสถานะวงเงินและเอกสาร

การ์ด "สรุปสถานะวงเงินและเอกสาร (รหัสที่เลือก)" แสดง วงเงินเครดิต (credit_money ของ master), จำนวนบิลขาย/ซื้อ (n ใบ) พร้อมยอดรวม, เช็คในมือ (n ใบ) พร้อมยอด และโทรศัพท์ติดต่อ (บรรทัด 305-327) ตัวเลขดึงตอนเลือกรายการ (loadCustDetails บรรทัด 105-171)

ช่องขวาบน: รายการสินค้า + ประวัติบิลของสินค้า

  • "รายการสินค้าที่ขาย/ซื้อ" (หัวกริดบรรทัด 340) คอลัมน์ รหัสสินค้า / ชื่อสินค้า / จำนวน / มูลค่ารวม รวมจาก ic_trans_detail ต่อรหัสสินค้า เรียงตามมูลค่ารวมมากไปน้อย สูงสุด 100 รายการ ชื่อสินค้าใช้ชื่อในบรรทัดเอกสารก่อน ถ้าว่างใช้ชื่อจาก ic_inventory (บรรทัด 110-121) คลิกแถวเพื่อเลือกสินค้า (บรรทัด 358)
  • "ประวัติบิลของสินค้า <รหัส>" (หัวกริดบรรทัด 381) คอลัมน์ วันที่ / เลขที่เอกสาร / จำนวน / ราคา / รวมเงิน ของสินค้าที่เลือกกับลูกค้าที่เลือก เรียงใหม่สุดก่อน สูงสุด 50 แถว (บรรทัด 177-199, 381)
  • เลือกลูกค้าใหม่แล้วระบบเลือกสินค้าแรกในรายการให้ทันที (setSelectedItemCode(firstItem) บรรทัด 158)

ช่องขวาล่าง: สรุปยอดรายเดือน 12 เดือน แยกตามปี

ตารางปี (ใหม่สุดก่อน) × ม.ค.–ธ.ค. + "รวมทั้งปี" ใช้ SUM(CASE WHEN EXTRACT(MONTH …)) ต่อปีของ doc_date (บรรทัด 134-151, 423-437) ถ้าไม่มีข้อมูลขึ้น "ไม่มีข้อมูลรายเดือน" (บรรทัด 444)

เอกสารที่นับ (trans_flag)

ข้อควรระวัง

  • นับใบสั่งขาย (36) รวมกับใบขาย (44) ในยอดเดียวกัน ถ้าสั่งขายแล้วออกใบขายต่อ ยอดสะสมอาจซ้ำสองเท่า และไม่นับ 48 (รับคืน/ลดหนี้) หรือ 144 (ใบกำกับเต็มรูป) จึงไม่ใช่ยอดขายสุทธิ ฝั่งซื้อไม่นับ 16 (ส่งคืน/ลดหนี้) ด้วย (บรรทัด 39 เทียบ รหัสชนิดเอกสาร trans_flag และทิศทางสต็อก (Trans Flag Map))
  • ประวัติบิลของสินค้า (50 แถว) ไม่กรอง last_status ต่างจากอีก 4 คิวรีที่ตัดเอกสารยกเลิก — บิลที่ยกเลิกแล้วอาจโผล่ในช่องนี้ (คิวรีบรรทัด 177-195)
  • สรุปเช็คในมือไม่กรองตาม chq_type กรองเพียง ap_ar_code ตรงกับรหัสที่เลือก และ status=0 (บรรทัด 129-133) เช็คทั้งรับและจ่ายของรหัสนั้นปนกัน ดูตาราง ทะเบียนเช็ค/บัตรเครดิต/กระเป๋าเงิน (cb_chq_list)
  • ยิง SQL จากเบราว์เซอร์ (ข้อยกเว้นของหลัก "รายงานผ่าน backend") สอดคล้องกับ ตัวเรียก API และตัวประกอบ SQL ฝั่งเบราว์เซอร์ (api-client, query-client, sml-query-builder)
  • โหลดรายชื่อซ้ำเกินจำเป็น: loadCustomers มี keyword, onlyWithDebt และ selectedCust ในรายการ deps ของ useCallback (บรรทัด 99) และ useEffect เรียกซ้ำทุกครั้งที่ฟังก์ชันเปลี่ยน (บรรทัด 101-103) จึงเกิดการค้นหาทุกครั้งที่พิมพ์ทีละตัวอักษร และโหลดรายชื่อใหม่ทุกครั้งที่คลิกเลือกแถว (คิวรีมี subquery SUM ต่อลูกค้า 100 ราย)
  • ตัวเลขเงินแสดงด้วย formatMoneyDisplay(…, getSmlDecimals(…)) จากสตริง ::text ของ SQL ไม่ผ่าน JS float จริง แต่ .filter(Number(balance_amount) > 0) ของโหมด "เฉพาะมียอด" แปลงเป็น Number เพื่อเปรียบเทียบกับศูนย์เท่านั้น (บรรทัด 93) ดูหลักใน ตัวเลข เงิน ภาษี และปี พ.ศ. ฝั่ง frontend (numeric.ts)
  • สรุปสถานะ "วงเงินเครดิต" เป็นค่า master ไม่ใช่ยอดคงค้างจริง จึงไม่ใช้ตัดสินได้ว่าเกินวงเงินหรือไม่ เทียบกับหน้าที่ตรวจวงเงินจริงใน ป๊อปอัปราคาขาย ต้นทุน และอนุมัติวงเงินเครดิต (PriceFormulaModal / PriceInfoModal / CostLockModal / CreditApproveModal)

ที่มาในโค้ด

  • ตัวคอมโพเนนต์ โหมด flag และตาราง master: frontend/account/report/BuySaleInformationScreen.tsx:27-40
  • โหลดรายชื่อ (ILIKE, balance subquery, LIMIT 100): …/BuySaleInformationScreen.tsx:63-103
  • โหลดรายละเอียดลูกค้า (สินค้า, ยอดบิล, เช็ค, รายเดือน): …/BuySaleInformationScreen.tsx:105-171
  • ประวัติบิลของสินค้า (LIMIT 50): …/BuySaleInformationScreen.tsx:173-199
  • ส่วนหน้าจอ (หัว, ปุ่ม, 4 ช่อง): …/BuySaleInformationScreen.tsx:202-450
  • ลงทะเบียน 2 คีย์: frontend/account/tabs/screenRegistry.tsx:741-765
  • alias ไปเมนูรายงานปัจจุบัน: frontend/src/config/smlMenu.ts:212-213
  • ดูภาพรวมจอรายงานทั้งหมดที่ จอรายงานกลาง (Universal Report Screen) และผังเมนูที่ สารบัญหน้าจอทั้งหมดของ SML Ai Account (ต้นไม้เมนู → หน้าจอ → โน้ต)