top of page
ค้นหา
รูปภาพนักเขียนSathit Jittanupat

Parse the Discount Expression with JavaScript

หากคุณเป็นผู้ประกอบการ กำลังหาโปรแกรมบัญชีใช้ในกิจการของคุณ ผมมีคำแนะนำที่อยากจะบอก ถ้าเป็นไปได้เลือกโปรแกรมที่พัฒนาโดยคนไทยดีกว่า หากธุรกิจของคุณไม่ใช่เป็นการขายปลีกหรือให้บริการลูกค้ารายย่อย แต่ต้องขายให้กับคู่ค้าที่เขาก็ทำธุรกิจเช่นกัน โดยเฉพาะอย่างยิ่งหากอยู่ในกลุ่มธุรกิจที่แข่งขันสูงเลือดสาด


เชื่อหรือไม่ว่าโปรแกรมมีชื่อเสียงของต่างประเทศ มีเงื่อนไขการขายหลายกรณีที่ใช้ไม่ได้หรือไม่สามารถรองรับ เมื่อเจอการใช้เงื่อนไขการค้าระดับท้องถิ่นในเมืองไทย​


กลยุทธขายเงินเชื่อ แฝงมากับศาสตร์การตั้งราคาสินค้า ใช้วัดความทักษะคำนวณต้นทุนทางการเงิน บีบคู่แข่งที่สายป่านสั้น (เงินหมุนเวียนน้อย) และแข่งกันที่ประสิทธิภาพในการติดตามหนี้ (วางบิลเก็บเงิน)


ส่วนลดเป็นอีกสมรภูมิหนึ่ง ที่ใช้สับประยุทธประจันบาญกันระยะประชิดเพื่อช่วงชิงความได้เปรียบและทำลายคู่แข่งในช่วงเวลาสั้น ๆ


บางครั้งส่วนลดใช้ประโยชน์เป็นดัชนีสำหรับสื่อสารที่เรียบง่าย เป็นคู่กับการกำหนดราคาขายปลีกราคาเดียว ในการแบ่งลำดับชั้นของห่วงโซ่สินค้า ค้าส่ง ค้าปลีก รายใหญ่ รายย่อย


เงื่อนไขส่วนลดที่แตกต่าง


อธิบายตัวอย่างกรณีใช้งานจริง


ลดเปอร์เซ็นต์

ใช้เป็นค่าเปอร์เซนต์ตามปกติ เช่น 15%

หลายแห่งใช้ระบบตั้งราคาตามกลุ่มสินค้าและกลุ่มลูกค้า สะดวกต่อการกำหนดราคาขายและสื่อสารกับคู่ค้า


ลดหลายชั้น

ลดหลายชั้นมักหมายถึงการลดแล้วลดอีกซ้อนกัน เช่น 10%5% 


เรามักใช้กับเงื่อนไขพิเศษ เช่น โปรโมชั่นเมื่อซื้อตามเงื่อนไขกำหนด, กรณีเมื่อชำระเป็นเงินสด


ลดเป็นบาท

ใช้กรณีลดมูลค่ารวมสุทธิ หรือ ลดราคาขายต่อหน่วย เช่น


  • 15 สำหรับลดที่มูลค่ารวม 

  • 5| สำหรับลดที่ราคาต่อหน่วย


โดยทั่วไปไม่ค่อยมีใครใช้ตั้งราคาขาย ยกเว้นเป็นเทคนิคการตลาดที่การแสดงตัวเลขส่วนลดแบบนี้ดึงดูดความสนใจมากกว่าตัวเลขที่เป็นเปอร์เซนต์ เช่น สินค้าราคา 1 หมื่นบาท ลด 999 บาท ดึงดูดใจกว่า 10% 


หลายครั้งที่เจอมักเกิดในขั้นตอนต่อรองราคา เช่น สินค้าราคา 125 บาท ต่อรองให้ลด 5 บาท เหลือชิ้นละ 120 บาท หรือ ซื้อสินค้า ราคา 125 บาท 3 ชิ้น ต่อรองให้ลดยอดรวม 5 บาท เหลือ 370 บาท



ลดแล้วปัดเศษ

ใช้กรณีคำนวณส่วนลดแล้วมีเศษสตางค์ ต้องการให้ปัดเศษเป็นจำนวนเต็มหรือเศษสตางค์ที่สามารถทอนได้ เช่น 15%1~ 


  • 1~ ปัดเศษให้เต็มบาท

  • .25~ ปัดเศษทีละสลึง (25 สตางค์)

  • .01~ ปัดให้เป็นทศนิยม 2 ตำแหน่ง (1 สตางค์) กรณีคำนวณแล้วได้ทศนิยมมากกว่า 2 ตำแหน่ง


ลดเพิ่มปิดท้าย

คล้ายกับลดหลายชั้นแต่ชั้นสุดท้ายลดเป็นเงินบาท กรณีต่อรองปัดเศษตอนจบ เช่น 15%3.75 หลังจากลด 15% แล้วโดนต่อรองให้ลดอีก 3.75 บาท


กรณีอื่น

คำสั่งส่วนลด สามารถประยุกต์ใช้เพื่อคำนวณกรณีอื่น เช่นในเอกสารรับและจ่ายได้ด้วย


  • ใช้คำนวณลอย (ไม่ได้หักลบกับมูลค่าสินค้า) กรณีคำนวณหักภาษี ณ​ ที่จ่าย เช่น =-3% 

  • ใช้คำนวณลอย กรณีชาร์จค่าบัตรเครดิต โดยใช้เครื่องหมายบวก เช่น =+5% 

  • ใช้คำนวณอัตราแลกเปลี่ยน โดยใช้เครื่องหมายคูณ เช่น =x34.4143



JavaScript code

โค้ดนี้เป็นโค้ดเก่า เพิ่งนำมาปรับปรุงให้รองรับกรณีประยุกต์ใช้คำนวณอัตราแลกเปลี่ยน คิดว่าอาจเป็นประโยชน์จึงนำมาเผยแพร่ เผื่อว่าโปรแกรมบัญชีของเมืองไทยจะเข้าใจภาษาส่วนลดเป็นมาตรฐานเดียวกัน


มีฟังก์ชั่นหลัก parseDscExp และฟังก์ชั่นย่อย roundStep ที่ใช้คำนวณปัดเศษ (เอาไปใช้เป็นฟังก์ชั่นอรรถประโยชน์ด้วยก็ได้) กลไกหลักที่สำคัญอยู่ที่การใช้ RegExp ตัดข้อความส่วนลดออกมาเป็นชิ้น ๆ เพื่อคำนวณทีละชั้นไปเรื่อย ๆ ได้


roundStep

var roundStep = function(stepstr, val) {
  var v = +(val || 0)
  if (v && stepstr) {
    var step = Math.abs(stepstr) || 1
    var pmode = 'round'

    if (stepstr[0]=='-')
      pmode = 'floor'

    if (stepstr[0]=='+')
      pmode = 'ceil'

    v = Math[pmode](v / step) * step
  }
  return v
}

parseDscExp


var parseDscExp = function (dscstr, val, pmode) {
   
  var _parsing = function(dstr) {
    if (!dstr)
      return;

    pmode = pmode || '-'

    var segs = dstr.toUpperCase().split(/([=]?[-+]?(?:[0-9]*[.0-9])?[0-9]+[%'/X~]|[X~]?[-+]?(?:[0-9]*[.0-9])?[0-9]+|[~/])/)

    var pmfn = {
      '-' : function(v, xv) { return isNaN(xv)? v : v - (+xv) },
      '+' : function(v, xv) { return isNaN(xv)? v : v + (+xv) },
      '=' : function(v, xv) { return isNaN(xv)? v : +xv },
      'X' : function(v, xv) { return  isNaN(xv)? v : v * (+xv) },
      "'" : function(v, xv) { return (isNaN(xv) || !(+xv))? v : v / (+xv) },
      '~' : function(v, xv) { return roundStep((isNaN(xv) || !xv)? '.01' : xv, v ) },
    }

    var opfn = {
      '%' : function(v, n, xfn) { return xfn(v, pmfn['X'](v, n) / 100) },
      "'" : function(v, n, xfn) { return xfn(v, pmfn["'"](v, n)) },
      '/' : function(v, n, xfn) { return xfn(v, n) },
      'X' : function(v, n, xfn) { return pmfn['X'](v, n) },
      '~' : function(v, n, xfn) { return pmfn['~'](v, n) },
    }

    for (var i = 1; i < segs.length; i+=2) {
      var dsc = segs[i]

      if (i==1 && /[^'X~]$/.test(dsc)) {
        if ('-+'.indexOf(dsc[0])!= -1) {
          pmode = dsc[0]
          dsc = dsc.slice(1)
        }
      }

      var pm = pmode
      if (/^[=X~]/.test(dsc)) {
        pm = dsc[0]
        dsc = dsc.slice(1)
      }
 
      var op = '/'
      if (/[%'/X~]$/.test(dsc)) {
        op = dsc[dsc.length -1]
        dsc = dsc.slice(0, -1)
      }

      var fn = opfn[op]
      var pfn = pmfn[pm]

      val = fn(val, dsc, pfn)
    }
  }

  val = +(val || 0)

  if (dscstr) {
    dscstr = dscstr.split('\\')[0] // stripout comment
    dscstr.split(/[\s,]+/).forEach(_parsing)
  }

  return val
}

โค้ดอีกส่วนหนึ่งเป็นตัวอย่างการนำไปใช้แบบซับซ้อน สามารถแบ่งข้อความส่วนลดด้วยสัญญลักษณ์ | เป็น 2 ส่วน สำหรับแบ่งคำสั่งลดราคาต่อหน่วยและลดมูลค่ารวม


ถ้ามีส่วนลดที่อยู่หน้าสัญญลักษณ์ดังกล่าว จะใช้ราคาต่อหน่วยไปคำนวณส่วนลดเพื่อหาราคาต่อหน่วยสุทธิก่อน โดยใช้ฟังก์ชั่น parseDscExp หากอยู่ด้านหลังใช้คำนวณกับมูลค่ารวม (ราคาคูณจำนวน) ด้วยฟังก์ชั่นเดียวกันอีกครั้ง


ตามปกติถ้าไม่มีสัญญลักษณ์ | หมายถึง ส่วนลดมูลค่ารวม


// ตัวอย่าง สินค้าราคา 125 บาท จำนวน 3 ชิ้น ส่วนลด 5|10%
var price = 125
var qty = 3
var dsc = '5|10%'

// แยกส่วนลด ['5', '10%']
var dsegs = dsc.split('|')
var dsc2 = dsegs.pop()
var dsc1 = dsegs.join('|')

// คำนวณราคาสุทธิ ส่วนลด '5' กับราคาต่อหน่วย => 120
var netprice = parseDscExp(dsc1, price)

// คำนวณมูลค่ารวม 120 * 3 = 360
var amount = netprice * qty

// คำนวณมูลค่าสุทธิ ส่วนลด '10%' กับมูลค่ารวม 360 => 324
var netamount = parseDscExp(dsc2, amount)

สุดท้ายคือความจริงที่ย้อนแย้ง ไม่มีใครใช้ส่วนลดจัดเต็มทุกแบบ โค้ดที่อุตส่าห์คำนวณได้สารพัด กิจการแต่ละแห่งต่างก็เลือกใช้แค่หนึ่งหรือสองกระบวนท่าถนัด หรือตามที่แวดวงธุรกิจแบบเดียวกันเขาใช้ เพียงแต่ทำออกมาแล้วใช้ได้ทั่วไป ช่วยให้รองรับวิธีคำนวณของธุรกิจแทบทุกประเภทในเมืองไทย โดยไม่ต้องมีโค้ดเฉพาะหลายเวอร์ชั่น


ข้อดีของการออกแบบส่วนลดให้เป็น expression ทำให้ออกแบบโครงสร้างภาษาเพิ่มเติมได้ในอนาคต เช่น ตรวจพบคำว่า "แถม" ก็อาจคำนวณจำนวนเงินเป็น 0


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

ดู 2 ครั้ง0 ความคิดเห็น

โพสต์ล่าสุด

ดูทั้งหมด

留言


Post: Blog2_Post
bottom of page