วันอาทิตย์ที่ 1 มิถุนายน พ.ศ. 2557

โปรโมชั่น 1 แถม 1 ใครว่าง่าย คิดชุ่ยๆ ก็เจ๊งกาโบ๊ง

วันนี้ ผมจะมาเล่า ประสบการณ์การ รับงานมาชิ้นนึง ซึ่งเป็นงานระบบขาย โดยเงื่อนไขของ รายการส่งเสริมการขาย รายการนี้คือ รายการ ซื้อ 1 แถม 1 แน่นอนฟังดูแล้วมันไม่ยากใช่ไหมหละ ตอนแรกผมก็คิดเช่นนั้น แต่เมื่อผมได้รับรายละเอียด Requirement แล้ว ผมเองก็ยังคิดว่ามันง่ายอยู่ "นรกกำลังบังเกิด" ด้วยความสะเพร่า และความขี้เกียจ ที่ปกติเราคิดว่า ฝีมือเราคงเขียนได้อยู่แล้ว ประมาทสุดๆ จึงได้เริ่มลงมือเขียน โดยที่ Application ตัวนี้ ใช้ Technology Web Base โดยใช้สถาปัตยกรรม ฝั่ง Microsoft ซึ่งตัวผมเองนั้น ถนัดอยู่แล้ว เอาละผมจะมาสรุปความประมาทของตัวเอง ที่ทำให้เสียเวลาในการเขียนโปรแกรม ไปหลายวันแถมเครียดอีกตะหากให้ฟัง

โดยที่เงื่อนไขการขายจะเป็นเช่นนี้
1. รายการที่แถมฟรีจะต้องมีราคาต่ำกว่ารายการที่ซื้อ
2. เวลาคีย์ขาย ไม่จำเป็นต้องเรียงคู่รายการ เช่นรายการที่ 1 เป็นรายการที่จะต้องเสียเงิน ส่วนรายการที่ 2 เป็นรายการที่จะได้รับฟรี แต่อาจจะคีย์เป็น รายการที่ 2 เป็นรายการเสียเงินและรายการที่ 1 เป็นรายการที่ได้ฟรี เป็นต้น
3. โปรแกรมจะต้องเลือกจับคู่รายการที่สามารถมอบส่วนลดให้ลูกค้าได้มากที่สุด (เงื่อนไขนี้เป็นเงื่อนไขที่ทราบทีหลังโดยที่ตัวผมเองไม่ได้คาดคิดมาก่อน เพราะไม่ได้ถามโดยละเอียด)

เริ่มต้นผมก็จินตนาการ เสต๊ปของการขายตามแบบที่ ทำประจำ โดย Algorithm แรกที่ผมเขียนได้เป็นลักษณะดังนี้

เงื่อนไขที่ทางผมกำหนดเพิ่มเติมไว้คือ สามารถคีย์ปริมาณสินค้าได้แค่ครั้งละ 1 ชิ้นต่อรายการเท่านั้น

องค์ประกอบบางส่วน ใน Domain Class SaleDetail

Public Class SaleDetail
{
 Public int Item { get; set; }

 Public string SaleNo { get; set; }
 Public string ProCode { get; set; }
 Public int Unit { get; set; }
 Public decimal Price { get; set; }
 Public decimal Discount { get; set; }
 Public decimal Total { get { return (this.Price * this.Unit) - this.Discount; ; } } 
}

องค์ประกอบบางส่วน ใน Domain Class SaleController


private List<SaleDetail> SaleDetails { get; private set;}
private void CalculateBuy1Get1()
{
 int getUnit = (int)this.SaleDetails.Count / 2; //จำนวนที่ควรได้รับฟรี
 if (getUnit > 0)
 {
  int setUnit = 0; // จำนวนที่ระบุฟรี
  var items = this.SaleDetails.OrderBy(d => d.Price).ToList();
  for (int i = 0; i < this.SaleDetails.Count; i++)
  {
   var item = items[i];
   if (setUnit < getUnit && items[this.SaleDetails.Count - (i + 1)].Price > item.Price)
   {
    item.Discount = item.Price;
    item.PromotionCode = "XYZ0005799999-GUHR";
    setUnit++;
   }
   else
   {
     // TODO Reset Item Price to Default Sale price
   }
  }
 }
}



จากโค๊ด Methode CalculateBuy1Get1() นั้นดูเหมือนง่าย เพราะวิธีนี้ผมใช้การ เรียงจากรายการสินค้าโดยใช้ ราคาเปรียบเทียบ จากน้อยไปหามาก จากนั้น ทำไปเทียบกับรายการ นับจากล่างสุดย้อนกลับขึ้นมา ซึ่งรายการ ล่างสุดจะเป็นรายการที่มีราคาแพงที่สุด

ยกตัวอย่างเช่น
1. นมสด      1 ชิ้น 100
2. เนย          1 ชิ้น 125
3. รังผึ้ง        1 ชิ้น 135
4. นมอัดเม็ด 1 ชิ้น 145
5. แซนวิส     1 ชิ้น 155
6. มันฝรั่ง     1 ชิ้น 165

เมื่อทำการจับคู่จะได้
6. มันฝรั่ง     1 ชิ้น 165 แถมฟรี 1. นมสด      1 ชิ้น 100
5. แซนวิส     1 ชิ้น 155 แถมฟรี 2. เนย          1 ชิ้น 125
4. นมอัดเม็ด 1 ชิ้น 145 แถมฟรี 3. รังผึ้ง        1 ชิ้น 135

ปัญหานี้จะเกิดปัญหาเมื่อ รายการที่ 3 กับ 4 ดันมีราคาเท่ากัน

1. นมสด      1 ชิ้น 100
2. เนย          1 ชิ้น 125
3. รังผึ้ง        1 ชิ้น 135
4. นมอัดเม็ด 1 ชิ้น 135
5. แซนวิส     1 ชิ้น 155
6. มันฝรั่ง     1 ชิ้น 165

เมื่อทำการจับคู่จะได้
6. มันฝรั่ง     1 ชิ้น 165 แถมฟรี 1. นมสด      1 ชิ้น 100
5. แซนวิส     1 ชิ้น 155 แถมฟรี 2. เนย          1 ชิ้น 125
4. นมอัดเม็ด 1 ชิ้น 135 แถมไม่ได้ 3. รังผึ้ง        1 ชิ้น 135

ผู้อ่านลองคิดเล่นๆดูก่อนครับ แล้วจะมาต่อวันหลังอีกที