[報表程式 - 2] 多個觸發點 => 繼承

承上題 [報表程式 - 1] 單一觸發點

今天我們稍微把上次的例子做個變化

1. 當報進站事件 ( MoveIn ) => 數量 (Qty) 都要 +1

2. 當報出站事件時 ( MoveOut ) => 數量 (Qty) 都要 -1

但除此之外,其他欄位邏輯都相同

 

這個例子我會分成四種情境講解

剛好對應到寫報告程式時 最常見的四種型態

這篇是2. 兩事件 (繼承)

完整程式碼請見 https://gitlab.com/jesperlai/Report

 

主要的變化為

1. Controller.cs不見了 => 共用的邏輯寫在BaseEvent.cs中,各Event相異的邏輯在各Event.cs中

2. Helper裡面的取TriggerPoint的檔案也不見了 => 轉移到各Event.cs中

 

故Program.cs會變成

using Sample_2.Event;
using Sample_2.Models;
using Sample_2.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Sample_2
{
    class Program
    {
        private static BuildEventParam MakeBuildEventParam(string eventName)
        {
            return new BuildEventParam
            {
                //為了方便講解 (通常這兩個值會從外面傳進來)---------
                STime = DateTime.Parse("2001/1/1"),
                ETime = DateTime.Parse("2001/2/1"),
                //--------------------------------------------------
                EventName = eventName,
            };
        }

        static void Main(string[] args)
        {
            var result = new List<Report>();

            //進站
            BaseEvent moveIn = new Event_MoveIn(MakeBuildEventParam("這是一個進站事件"));
            result.AddRange(moveIn.Run());

            //出站
            BaseEvent moveOut = new Event_MoveOut(MakeBuildEventParam("這是一個出站事件"));
            result.AddRange(moveOut.Run());

            //寫出檔案
            RptService myRpt = new RptService();
            result = result.OrderBy(q => q.Txn_Dt).ToList();  //最後輸出資料要以過站時間排序
            myRpt.GenFile(result, @"D:\sample.csv");
        }
    }
}

 

Event資料夾下

BaseEvent.cs

using Sample_2.Extensions;
using Sample_2.Helper;
using Sample_2.Models;
using Sample_2.Utility;
using Sample_2.ViewModels;
using System.Collections.Generic;

namespace Sample_2.Event
{
    public abstract class BaseEvent
    {
        private DataAccessHelper _helper;
        protected Repository repo;
        protected BuildEventParam builderParam;

        public BaseEvent(BuildEventParam param)
        {
            builderParam = param;
            repo = new Repository();
            _helper = new DataAccessHelper(repo);
        }

        public List<Report> Run()
        {
            var triggerPoint = GetTriggerPoint();
            return GetData(triggerPoint);
        }

        public abstract List<Lot_Txn> GetTriggerPoint();

        public virtual List<Report> GetData(List<Lot_Txn> triggerPoints)
        {
            var dataSet = _helper.ConcreteDataSet(triggerPoints);

            var result = new List<Report>();
            //我把Trigger Point 觸發點 縮寫成tp
            foreach (var tp in triggerPoints)
            {
                //該回合需用到的資料 我把this round 縮寫成 tRound
                var tRound = DataAccessHelper.GetThisRoundData(dataSet, tp);

                //Controller 盡量扁平 如果有複雜的運算可以放到 Utility 做
                var item = new Report
                {
                    Txn_Dt = tp.Txn_Dt,
                    Lot_No = tp.Lot_No,
                    Stage_Id = tp.Stage_Id,
                    Qty = tp.Qty.Trim(),   //有些轉型或是常用的運算 寫成extension會比較易用
                    Po_No = tRound.So.Po_No,
                    Order_Qty = tRound.So.Qty,
                    Sod = DataUtility.GetSod(tRound.So),  //假設這個欄位有很複雜的邏輯 放到Utitlity做
                    Event_Name = builderParam.EventName,
                };

                result.Add(item);
            }

            return result;
        }
    }
}

 

Event_MoveIn.cs

using Sample_2.Models;
using Sample_2.ViewModels;
using System.Collections.Generic;

namespace Sample_2.Event
{
    public class Event_MoveIn : BaseEvent
    {
        public Event_MoveIn(BuildEventParam param) : base(param)
        {

        }

        public override List<Lot_Txn> GetTriggerPoint()
        {
            var txns = repo.GetTxn(builderParam.STime, builderParam.ETime, "進站");

            return txns;
        }

        public override List<Report> GetData(List<Lot_Txn> triggerPoints)
        {
            var result = base.GetData(triggerPoints);

            //處理一些該 event 特別不同於 base event 的地方
            foreach (var item in result)
            {
                item.Qty += 1;   //隨便舉例 假設進站數量都固定要 + 1 

                //通常還會有更多更多相異處
                //通常還會有更多更多相異處
                //通常還會有更多更多相異處
                //通常還會有更多更多相異處
            }

            return result;
        }
    }
}

 

Event_MoveOut.cs

using Sample_2.Models;
using Sample_2.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Sample_2.Event
{
    public class Event_MoveOut : BaseEvent
    {
        public Event_MoveOut(BuildEventParam param) : base(param)
        {

        }

        public override List<Lot_Txn> GetTriggerPoint()
        {
            var txns = repo.GetTxn(builderParam.STime, builderParam.ETime, "出站");

            return txns;
        }

        public override List<Report> GetData(List<Lot_Txn> triggerPoints)
        {
            var result = base.GetData(triggerPoints);

            //處理一些該 event 特別不同於 base event 的地方
            foreach (var item in result)
            {
                item.Qty -= 1;   //隨便舉例 假設進站數量都固定要 - 1 

                //通常還會有更多更多相異處
                //通常還會有更多更多相異處
                //通常還會有更多更多相異處
                //通常還會有更多更多相異處
            }

            return result;
        }
    }
}

 

Helper 資料夾下

2_DataAccessHelper.TriggerPoint.cs

using Sample_1.Models;
using Sample_1.ViewModels;
using System.Collections.Generic;

namespace Sample_1.Helper
{
    public partial class DataAccessHelper
    {
        public TriggerPointAndDataSetVM InitializeData()
        {
            var data = new TriggerPointAndDataSetVM();

            data.Tp = GetTriggerPoints();
            data.DataSet = ConcreteDataSet(data.Tp);

            return data;
        }

        private List<Lot_Txn> GetTriggerPoints()
        {
            return _repo.GetTxn(_dataStartTime, _dataEndTime);
        }
    }
}

 

其他的程式碼幾乎都是跟單一Event的程式是一樣的

詳見 [報表程式 - 1 ] 單一觸發點