เชื่อมต่อ Lazada กับ Odoo: แมป SKU และกระทบยอดสต็อก
ผู้ขายบน Lazada ที่เราเคยทำงานด้วยในกรุงเทพฯ แทบทุกรายเจอปัญหาเดียวกัน แดชบอร์ดของมาร์เก็ตเพลสแสดงตัวเลขชุดหนึ่ง ทีมคลังสินค้าเห็นอีกชุดหนึ่ง ฝ่ายบัญชีไม่สามารถโยงตัวเลขทั้งสองชุดนี้เข้ากับยอดเงินที่เข้าบัญชีธนาคารได้เลย การเชื่อมต่อ Lazada กับ Odoo ที่ทำอย่างถูกต้องจะแก้ปัญหานี้ ระบบจะส่งทุกออเดอร์ การเคลื่อนไหวสต็อก และยอดจ่ายเงินให้ไหลผ่านบัญชีเดียวใน Odoo แทนที่จะกระจัดกระจายอยู่ในสเปรดชีตสามไฟล์ที่ไม่คุยกัน
บทความนี้จะพาไปดูวิธีที่เราวางระบบเชื่อมต่อ Lazada กับ Odoo จริง ๆ เราจะแมป SKU อย่างไร ทำอย่างไรให้สต็อกเป็นจำนวนเดียวกันทั้งใน Lazada ช่องทางหน้าร้าน และ Shopee และกระทบยอดรายงาน settlement ที่ออกทุกสองสัปดาห์ให้ตรงกับสิ่งที่ Odoo คาดว่าจะได้รับ ดูภาพรวมงานเชื่อมต่อระบบทั้งหมดของเราได้ที่หน้าบริการเชื่อมต่อ API กับ Odoo ซึ่งครอบคลุม Shopee และ TikTok Shop ด้วยเช่นกัน
ทำไมต้องแทนที่ Seller Center ในงานบัญชี
Lazada Seller Center ถูกออกแบบมาเพื่อจัดการลิสติ้งสินค้าและการจัดส่งออเดอร์ ไม่ได้ออกแบบมาเพื่องานบัญชีหรือบริหารสต็อกหลายช่องทาง ระบบบอกได้แค่ว่าออเดอร์ถูกสั่งซื้อและจัดส่งแล้ว แต่ระบบจะไม่บอกว่าการขายนั้นกระทบภาษีหัก ณ ที่จ่ายหรือไม่ ไม่บอกต้นทุนขายตอนปิดงบสิ้นเดือน และไม่บอกว่าสินค้ารหัสเดียวกันยังเหลือพอขายให้ลูกค้าขายส่งที่ซื้อหน้าร้านหรือไม่
เมื่อข้อมูลออเดอร์เข้ามาเป็นใบสั่งขาย (sales order) ใน Odoo ขั้นตอนถัดไปทั้งหมดจะทำงานตามปกติ ใบจัดส่งตัดสต็อกผ่านเส้นทางมาตรฐาน ใบแจ้งหนี้เป็นไปตามกฎ VAT และใบกำกับภาษีอิเล็กทรอนิกส์ของกิจการ ยอดขายนี้จะไปปรากฏในรายงานเดียวกับยอดขายหน้าร้านและลูกค้า B2B ความสม่ำเสมอแบบนี้คือเป้าหมายทั้งหมดของการเชื่อมต่อ หากไม่มีสิ่งนี้ กิจการกำลังบริหารธุรกิจสองธุรกิจที่บังเอิญใช้คลังสินค้าร่วมกันเท่านั้น
SKU mapping: จุดที่หลายคนมองข้าม
ลิสติ้งใน Lazada แทบไม่เคยใช้รหัส SKU เดียวกับที่กิจการใช้ใน Odoo อยู่แล้ว ผู้ขายมักสร้างรหัส SKU ระดับลิสติ้งแยกตามตัวเลือกสินค้า ชุดสินค้า (bundle) หรือชุดโปรโมชัน รหัสเหล่านี้เพิ่มจำนวนเร็วมากเมื่อสินค้ามีสีหรือขนาดบรรจุหลายแบบ
แนวทางที่เราใช้ในทุกโปรเจกต์คือ
- ใช้ internal reference ของ Odoo เป็นแหล่งข้อมูลหลักเพียงแหล่งเดียวสำหรับสินค้าแต่ละตัวแปร (variant)
- สร้างตารางแมปปิ้ง (อาจเป็น model ง่าย ๆ ใน Odoo หรือฟิลด์บน product variant) เก็บ SellerSku ของ Lazada คู่กับ product_id ของ Odoo
- จัดการ bundle อย่างชัดเจน หากลิสติ้งหนึ่งใน Lazada ขายสินค้า Odoo สามรายการเป็นชุดเดียว การเชื่อมต่อต้องแตกออเดอร์บรรทัดเดียวนั้นเป็นการเคลื่อนไหวสต็อกสามรายการ ไม่ใช่รายการเดียว
- ปฏิเสธ SKU ที่ยังไม่ได้แมปตั้งแต่ขั้นตอนซิงค์ ไม่ใช่ปล่อยให้เงียบหายไปภายหลัง ออเดอร์ที่ไม่มี SKU ตรงกันควรขึ้นเป็นคิวข้อผิดพลาดที่มองเห็นได้ชัดเจน ไม่ใช่หายไปใน log ของ cron job ที่ล้มเหลว
ตารางแมปปิ้งนี้คือส่วนที่ตัวเชื่อมต่อ "แบบง่าย" มักข้ามไป มันเป็นส่วนแรกที่พังเมื่อแคตตาล็อกสินค้าโตเกินสองสามร้อยตัวแปร หากแคตตาล็อกของกิจการกระจายอยู่หลายหน้าร้านออนไลน์แล้ว ทีมพัฒนาอีคอมเมิร์ซ ของเราช่วยวางขอบเขตงานทำความสะอาดข้อมูลเป็นระยะแยกต่างหากก่อนเริ่มสร้างตัวเชื่อมต่อได้
บัญชีสต็อกเดียวทั้งมาร์เก็ตเพลสและหน้าร้าน
คำถามที่สองที่พ่อค้าแม่ค้าทุกรายถามคือประมาณว่า ถ้าขายสินค้าชิ้นสุดท้ายบน Lazada ไปก่อนที่หน้าร้านจะขายห้านาที ระบบจะรู้ไหม คำตอบตรงไปตรงมาคือขึ้นอยู่กับความถี่ของการซิงค์ และทั้งสองช่องทางเขียนข้อมูลลง stock location เดียวกันใน Odoo หรือไม่
เราวางระบบให้ออเดอร์จากมาร์เก็ตเพลสเข้ามาเป็นใบสั่งขายที่ผูกกับคลังสินค้าเดียวกับที่ทีมหน้าร้านใช้ ระบบการจองสต็อก (reservation) ของ Odoo จะจัดการความขัดแย้งแบบเดียวกับที่จัดการออเดอร์หน้าร้านสองใบที่เข้ามาพร้อมกัน ใครจองก่อนได้ก่อน ใบที่สองจะกลายเป็น backorder เราดึงข้อมูลออเดอร์จาก Lazada order API เป็นระยะสั้น ๆ มักอยู่ระหว่างสองถึงสิบนาที ขึ้นอยู่กับปริมาณออเดอร์ของกิจการ เราไม่พึ่งพา webhook เพียงอย่างเดียว เพราะการส่ง webhook ไม่ได้รับประกันว่าจะมาถึงเสมอ ช่องว่างที่เงียบหายไปอันตรายกว่าความล่าช้าเล็กน้อย
ข้อจำกัดที่ต้องยอมรับตรงนี้คือ near-real-time ไม่เหมือนกับ real-time ในช่วง flash sale ที่ขายเร็วมาก หน้าต่างการซิงค์สองนาทีก็ยังอาจทำให้ขายเกินสต็อก (oversell) ได้ หากทั้งสองช่องทางขายสินค้าชิ้นสุดท้ายหมดในหน้าต่างเวลานั้นพอดี เราบรรเทาปัญหานี้ด้วยการกันสต็อกสำรองจำนวนเล็กน้อยไว้ในฟีดสต็อกที่ส่งให้ Lazada แทนที่จะเปิดเผยจำนวนคงเหลือเต็ม 100 เปอร์เซ็นต์ วิธีนี้แลกมาด้วยรายได้ที่เสียโอกาสไปเล็กน้อย แต่หลีกเลี่ยงต้นทุนจากการยกเลิกออเดอร์และความเสียหายต่อชื่อเสียงจากการขายเกินสต็อก
ซิงค์สต็อกกลับไปยัง Lazada
การซิงค์ทำงานสองทิศทาง ออเดอร์ไหลเข้ามา จำนวนสินค้าคงเหลือไหลออกไป เราส่งจำนวนคงเหลือของ Odoo ลบด้วยสต็อกสำรองและจำนวนที่จองไว้สำหรับช่องทางอื่น กลับไปยัง Lazada ผ่าน stock update API ในช่วงเวลาเดียวกับที่ดึงออเดอร์เข้ามา
จุดที่ยุ่งยากคือกรณีมีหลายคลังสินค้า หากผู้ขายจัดส่งจากทั้งคลังกรุงเทพฯ และคลังชลบุรี Lazada ต้องการเพียงตัวเลขเดียวต่อ SKU เราคำนวณตัวเลขนี้ที่ระดับสินค้าใน Odoo โดยรวมยอดจากคลังทั้งหมดที่มีสิทธิ์จัดส่งให้ Lazada ฝั่ง Lazada ไม่มีทางตีความตัวเลขดิบแยกตามคลังได้ถูกต้องอยู่แล้ว เราจึงไม่ส่งข้อมูลแบบนั้นออกไป
สถานะออเดอร์และขั้นตอนการจัดส่ง
วงจรออเดอร์ที่เรามักวางระบบให้มีลักษณะดังนี้
| สถานะใน Lazada | การทำงานใน Odoo |
|---|---|
| สั่งซื้อแล้ว | สร้างใบสั่งขาย ยืนยัน จองสต็อก |
| พร้อมจัดส่ง | สร้างใบจัดส่ง พิมพ์ฉลากจัดส่งของ Lazada |
| จัดส่งแล้ว | ยืนยันใบจัดส่ง บันทึกการเคลื่อนไหวสต็อก |
| ส่งถึงแล้ว | ไม่ต้องทำอะไรใน Odoo (ข้อมูลอ้างอิงเท่านั้น) |
| ตีกลับ / คืนสินค้า | สร้างใบคืนสินค้า รับสต็อกกลับหากทำได้ ออกใบลดหนี้ |
| ยกเลิกก่อนจัดส่ง | ยกเลิกใบสั่งขาย คืนการจองสต็อก |
การยกเลิกและการคืนสินค้าคือจุดที่มักเผยให้เห็นว่าตัวเชื่อมต่อแบบกำหนดเองเก่าหรือไม่ครบถ้วนแค่ไหน การคืนสินค้าที่ไม่ได้ถูกแมปเข้ากับใบลดหนี้และการรับสต็อกกลับอย่างถูกต้องใน Odoo จะทำให้ยอดขายที่รายงานสูงเกินจริงอย่างเงียบ ๆ และทำให้อัตราการคืนสินค้าต่ำกว่าความจริง เรื่องนี้ไปกระทบการวางแผนความต้องการสินค้าสำหรับใบสั่งซื้อครั้งถัดไปด้วย
กระทบยอด settlement เพื่อปิดวงจรร่วมกับฝ่ายบัญชี
Lazada จ่ายเงินตามรอบที่กำหนดตายตัว และหักค่าคอมมิชชัน ค่าธรรมเนียมการชำระเงิน เงินอุดหนุนค่าส่ง และบางครั้งค่าปรับ ก่อนโอนเงินเข้าบัญชีธนาคาร รายงาน settlement ที่ Lazada ให้มานั้นละเอียดก็จริง แต่ไม่ได้อยู่ในรูปแบบที่ฝ่ายบัญชีจะลงบันทึกบัญชีได้โดยตรง
ขั้นตอนกระทบยอดของเราคือ
- นำเข้ารายงาน settlement ไม่ว่าจะเป็นไฟล์ CSV หรือผ่าน API ตามระดับบัญชีผู้ขาย เข้าสู่ Odoo เป็นชุดที่ผูกกับช่วงวันที่ของรอบ settlement นั้น
- จับคู่ออเดอร์ที่ชำระเงินแล้วแต่ละรายการกลับไปยังใบสั่งขายและใบแจ้งหนี้ต้นฉบับ
- บันทึกค่าคอมมิชชัน ค่าโลจิสติกส์ และค่าปรับต่าง ๆ เป็นบรรทัดค่าใช้จ่ายแยกต่อออเดอร์ ไม่ใช่หักรวมเป็นก้อนเดียว เพื่อให้รายงานกำไรขั้นต้นต่อ SKU ยังแม่นยำ
- กระทบยอดเงินโอนสุทธิกับรายการจริงในใบแจ้งยอดธนาคาร โดยใช้ bank reconciliation ของ Odoo เราใช้วินัยแบบเดียวกันนี้กับระบบที่เชื่อมต่อผ่าน API ทั้งด้านการชำระเงินและออเดอร์ของช่องทางอื่น ตามแนวทางที่อธิบายไว้ในหน้าบริการที่ปรึกษา Odoo
- ตั้งสถานะข้อยกเว้นสำหรับออเดอร์ที่มีอยู่ใน Odoo แต่ไม่พบในชุด settlement และรายการ settlement ที่ไม่พบออเดอร์ตรงกันใน Odoo ให้ฝ่ายบัญชีตรวจสอบทุกสัปดาห์ แทนที่จะปล่อยไว้จนถึงสิ้นเดือน
ขั้นตอนสุดท้ายนี้สำคัญกว่าที่ฟังดู รอบเวลา settlement ของมาร์เก็ตเพลสแทบไม่เคยตรงกับเดือนปฏิทินพอดี หากไม่มีการตรวจสอบข้อยกเว้นรายสัปดาห์ ฝ่ายบัญชีจะต้องมานั่งอธิบายรายการที่ไม่ตรงกันสะสมหกสัปดาห์ในช่วงปิดงบ ซึ่งเป็นช่วงที่ไม่มีใครมีเวลาทำแบบนั้นจริง ๆ
สิ่งที่การเชื่อมต่อแก้ให้ไม่ได้ด้วยตัวเอง
การเชื่อมต่อ Lazada กับ Odoo ไม่สามารถแก้ไขแคตตาล็อกสินค้าที่มีข้อมูลซ้ำซ้อนหรือไม่สอดคล้องกันได้ และไม่สามารถย้อนกลับไปทำความสะอาดออเดอร์เก่าที่เคยกรอกมือก่อนตัวเชื่อมต่อจะเริ่มใช้งานได้ เราเคยเห็นโปรเจกต์ที่ต้องหยุดชะงักหลายสัปดาห์ เพราะงานทำความสะอาด SKU ใช้เวลานานกว่าการสร้างตัวเชื่อมต่อเองเสียอีก ควรวางแผนให้งานทำความสะอาดนี้เป็นระยะ (phase) ของตัวเอง มีขอบเขตงานและราคาที่ตายตัวของตัวเอง ไม่ใช่รวมเข้ากับไทม์ไลน์ของการเชื่อมต่อ
หากกิจการขาย Lazada ควบคู่ไปกับ Shopee, TikTok Shop หรือหน้าร้านจริง สถาปัตยกรรมเดียวกันนี้ขยายไปใช้กับแต่ละช่องทางได้ บัญชีสต็อกเดียวใน Odoo ตารางแมป SKU หนึ่งชุดต่อหนึ่งมาร์เก็ตเพลส และวินัยการกระทบยอดแบบเดียวกันสำหรับทุกรอบ settlement นี่คือรูปแบบที่เรานำไปใช้ในทุกงานเชื่อมต่อ API ไม่ว่ามาร์เก็ตเพลสใดจะเป็นลำดับแรกในรายการ สำหรับกิจการที่วางแผนเปิดหน้าร้านออนไลน์ของตัวเองควบคู่กับ Lazada ทีมพัฒนาเว็บไซต์ ของเราสามารถวางขอบเขตงานนั้นเป็นอีกระยะแยกต่างหากได้เช่นกัน



