CPF และ CNPJ เป็นหมายเลขสองตระกูลที่พบบ่อยในแบบฟอร์มของบราซิล ทั้งคู่ทำหน้าที่เป็นเลขประจำตัวผู้เสียภาษี แต่ใช้กับผู้ถือที่ต่างชนิดกัน และทั้งคู่มีหลักตรวจสอบอยู่ในตัว ทำให้ระบบสามารถกรองความผิดพลาดจากการพิมพ์ได้ก่อนที่ข้อมูลจะไหลเข้าสู่ขั้นตอนถัดไป การทำความเข้าใจว่าเมื่อใดควรใช้ตระกูลใด และการตรวจของทั้งสองตระกูลตอบคำถามอะไรได้บ้าง ช่วยลดทั้งการปฏิเสธที่ผิดและการยอมรับข้อมูลที่ควรถูกทักท้วง
CPF กับ CNPJ ต่างกันอย่างไร?
ความต่างข้อแรกคือชนิดของผู้ถือหมายเลข หมายเลขแบบแรกใช้กับบุคคลธรรมดา ส่วนแบบที่สองใช้กับนิติบุคคลซึ่งได้แก่บริษัทและองค์กรต่าง ๆ การเลือกใช้ผิดตระกูลจึงไม่ใช่แค่เรื่องรูปแบบ แต่เป็นเรื่องของประเภทเจ้าของข้อมูลที่ระบบเก็บ
ความต่างข้อที่สองคือบริบทการใช้งาน ทั้งสองแบบถูกใช้ในงานภาษี การเปิดบัญชี และการออกใบกำกับ แต่แบบของนิติบุคคลมักผูกกับข้อมูลขององค์กรที่ต้องตรวจสอบเพิ่มในชั้นอื่น เช่นชื่อบริษัทและที่อยู่จดทะเบียน
ความต่างข้อที่สามที่คนมักเข้าใจผิดคือ ทั้งสองแบบใช้แนวคิดการคำนวณหลักตรวจสอบแบบเดียวกัน ความต่างจริงอยู่ที่พารามิเตอร์ที่ใช้ ซึ่งได้แก่จำนวนหลักของหมายเลขและค่าที่ใช้ถ่วงน้ำหนัก การที่หน้าตาคล้ายกันนี้ทำให้ระบบที่สลับตระกูลกันโดยไม่ตั้งใจมักไม่ส่งข้อผิดพลาดออกมาในทันที
| ประเด็น | หมายเลขสำหรับบุคคลธรรมดา | หมายเลขสำหรับนิติบุคคล |
|---|---|---|
| ผู้ถือหมายเลข | บุคคลธรรมดา | บริษัทและองค์กร |
| จำนวนหลักตรวจสอบ | หนึ่งหลัก | สองหลัก |
| บริบทที่พบบ่อย | ภาษีบุคคล การเปิดบัญชี | ภาษีนิติบุคคล การออกใบกำกับ |
| ข้อมูลที่ต้องตรวจเพิ่ม | ข้อมูลส่วนบุคคลของผู้ถือ | ชื่อและที่อยู่จดทะเบียน |
โครงสร้างของหมายเลขทั้งสองแบบ
หมายเลขทั้งสองแบบประกอบด้วยส่วนที่เป็นเลขลำดับและส่วนที่เป็นหลักตรวจสอบซึ่งอยู่ท้ายสุด โดยแบบของบุคคลธรรมดามีหลักตรวจสอบหนึ่งหลักที่คำนวณจากเลขลำดับทั้งหมด ส่วนแบบของนิติบุคคลมีหลักตรวจสอบเพิ่มอีกหลักหนึ่งเพื่อให้ตรวจซ้ำอีกชั้น
ตัวคั่นที่เห็นในเอกสาร เช่นจุด ขีดกลาง และเครื่องหมายทับ เป็นเพียงเครื่องหมายเพื่อการอ่าน ไม่ได้เป็นส่วนหนึ่งของหมายเลข เมื่อระบบรับข้อมูลเข้ามาจึงต้องตัดอักขระเหล่านี้ออกก่อนเสมอ มิฉะนั้นหมายเลขเดียวกันที่ผู้ใช้พิมพ์มาสองรูปแบบจะถูกมองเป็นคนละค่า
การที่หมายเลขทั้งสองแบบมีหลักตรวจสอบซ้อนกันนี้มีข้อดีคือความผิดพลาดจากการพิมพ์หลักเดียวถูกจับได้เกือบทั้งหมด แต่ก็มีข้อควรระวังคือความผิดพลาดที่เกิดจากการสลับหลักซึ่งมีน้ำหนักเท่ากันอาจไม่ถูกจับ ซึ่งเป็นข้อจำกัดทั่วไปของตระกูลสูตรถ่วงน้ำหนัก ตามที่อธิบายไว้ในภาพรวมอัลกอริทึมหลักตรวจสอบ
แนวคิดการคำนวณหลักตรวจสอบ: ถ่วงน้ำหนักแล้วหารเอาเศษ
แนวคิดที่ใช้กับทั้งสองแบบไม่ต่างจากหมายเลขประเภทอื่นในตระกูลเดียวกัน คือนำตัวเลขแต่ละหลักมาคูณกับค่าถ่วงน้ำหนักประจำตำแหน่ง บวกผลคูณทั้งหมดเข้าด้วยกัน แล้วหารเอาเศษกับค่ามอดุลัส จากนั้นจึงแปลงเศษที่ได้ให้เป็นตัวอักษรหนึ่งตัว
จุดที่ต่างกันคือค่าถ่วงน้ำหนัก ตำแหน่งเริ่มนับ และวิธีจัดการเศษในกรณีที่เศษมีค่ามากกว่าสิบ แบบของนิติบุคคลยังทำซ้ำขั้นตอนเดิมอีกครั้งโดยใช้หลักตรวจสอบตัวแรกที่คำนวณได้เป็นส่วนหนึ่งของข้อมูลนำเข้า
สิ่งที่ผู้พัฒนาควรยึดถือคือคำอธิบายที่หน่วยงานผู้ประกาศมาตรฐานเผยแพร่ ไม่ใช่สูตรที่จำต่อกันมา เพราะรายละเอียดเช่นทิศทางการนับตำแหน่งเป็นจุดที่ทำให้สูตรหลายเวอร์ชันที่หมุนเวียนกันตามอินเทอร์เน็ตให้ผลไม่ตรงกัน
ทำไมชุดที่ทุกหลักซ้ำกันจึงต้องถูกตัดออก?
ชุดตัวเลขที่ทุกหลักเป็นค่าเดียวกัน เช่นชุดที่ขึ้นต้นด้วยศูนย์ล้วน หรือชุดที่มีตัวเลขหลักเดียวซ้ำกันตลอดทั้งชุด เป็นชุดที่ผ่านการคำนวณแบบถ่วงน้ำหนักได้อย่างไม่น่าเชื่อ เพราะผลรวมที่ได้มักลงตัวกับมอดุลัสพอดี เหตุผลคือความสัมพันธ์เชิงเส้นของสูตรทำให้ค่าซ้ำ ๆ ให้ผลลัพธ์ที่เป็นระเบียบเกินไป
ด้วยเหตุนี้ข้อกำหนดของบราซิลจึงระบุให้ตัดชุดที่ทุกหลักซ้ำกันออกจากการเป็นหมายเลขที่ใช้ได้ แม้ผลการคำนวณจะผ่าน นี่เป็นตัวอย่างที่ดีของหลักการว่า การตรวจด้วยสูตรไม่ควรถูกใช้เป็นคำตอบสุดท้ายเพียงลำพัง เพราะยังมีกรณีขอบที่ต้องใช้กฎเพิ่มเติมปิดช่องว่าง
สำหรับทีมทดสอบ ชุดที่ทุกหลักซ้ำกันจึงมีค่ามากในฐานะกรณีทดสอบ เพราะเป็นชุดที่ผ่านการคำนวณแต่ต้องถูกปฏิเสธโดยกฎชั้นถัดไป หากระบบของคุณตอบกลับว่าถูกต้อง แปลว่ายังขาดกฎชั้นนี้
ผ่านการตรวจกับสถานะการจดทะเบียนเป็นคนละเรื่อง
การผ่านการคำนวณบอกได้เพียงว่าชุดตัวเลขถูกสร้างตามกฎเดียวกับหมายเลขอื่น ไม่ได้บอกว่าผู้ถือหมายเลขนั้นจดทะเบียนอยู่จริง ยังดำเนินกิจการอยู่ หรือมีสถานะทางภาษีเป็นปกติ
การยืนยันสถานะต้องสอบถามไปยังฐานข้อมูลของหน่วยงานจัดเก็บภาษี ซึ่งเป็นการทำงานคนละชั้นและมีข้อจำกัดเรื่องสิทธิ์การเข้าถึงและเวลาตอบกลับ เครื่องมือที่ซื่อสัตย์จึงต้องแยกคำตอบสองชั้นนี้ออกจากกันให้ชัดเจน
ในหน้าจอผู้ใช้ ควรแสดงผลสามเรื่องแยกกัน ได้แก่รูปแบบที่กรอกสอดคล้องหรือไม่ ผลการคำนวณหลักตรวจสอบ และสถานะการจดทะเบียนถ้ามีการสอบถาม การรวมสามเรื่องนี้เป็นข้อความเดียวจะทำให้ผู้ใช้ไม่รู้ว่าต้องแก้ที่ใด และทำให้เจ้าหน้าที่เข้าใจผิดว่าหมายเลขที่ผ่านการคำนวณแปลว่าจดทะเบียนแล้ว
เมื่อต้องตรวจหมายเลขจากหลายประเทศพร้อมกัน การแยกชั้นแบบนี้ยิ่งสำคัญ เพราะแต่ละประเทศมีเกณฑ์ต่างกัน ตามที่อธิบายไว้ในการตรวจสอบเลขประจำตัวของแต่ละประเทศ
สำหรับนักพัฒนา: ทำความสะอาดข้อมูลก่อน แล้วจึงตรวจ
ขั้นตอนแรกที่ควรทำคือตัดอักขระคั่นทั้งหมดออก และปรับตัวอักษรให้อยู่ในรูปเดียวกันก่อนเปรียบเทียบ ขั้นตอนนี้ควรเกิดก่อนการตรวจซ้ำว่าข้อมูลชุดเดียวกันถูกส่งเข้ามาสองครั้ง มิฉะนั้นรายการเดียวกันที่พิมพ์ต่างรูปแบบจะถูกนับเป็นสองรายการ
ถัดมาคือแยกตรรกะของสองตระกูลออกจากกันให้ชัด แม้ทั้งคู่จะใช้โครงเดียวกัน แต่การนำกฎของตระกูลหนึ่งไปใช้กับอีกตระกูลเป็นความผิดพลาดที่เกิดขึ้นบ่อยและตรวจพบได้ยาก เพราะหมายเลขผิดตระกูลมักยังผ่านการคำนวณของตระกูลที่ผิดอยู่ดี
สุดท้ายคือออกแบบข้อความตอบกลับให้บอกได้ว่ารูปแบบไม่ตรงกับตระกูลใด หรือหลักตรวจสอบไม่สอดคล้องกับตระกูลใด และถ้าระบบไม่รู้ว่าข้อมูลชุดนี้ควรเป็นตระกูลใด ให้บอกว่ายังไม่มีกฎแทนการเดา ตัวอย่างการทำงานทั้งหมดในบทความนี้สามารถลองได้ที่เครื่องมือตรวจสอบ ซึ่งแสดงผลแยกตามชั้นให้เห็นชัดเจน
ก้าวต่อไป
เริ่มจากการตรวจว่าระบบของคุณตัดอักขระคั่นก่อนตรวจหรือไม่ แล้วจึงตรวจว่ามีกฎตัดชุดตัวเลขที่ทุกหลักซ้ำกันออกหรือยัง สองข้อนี้เป็นจุดที่ทำให้ผลการตรวจต่างกันมากที่สุดในทางปฏิบัติ
ตัวอย่างในบทความนี้ไม่ได้เป็นเลขประจำตัวผู้เสียภาษีของบุคคลหรือบริษัทใด และไม่สามารถใช้ยืนยันสถานะการจดทะเบียนได้