using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using AMESCoreStudio.WebApi;
using AMESCoreStudio.WebApi.Models.BAS;
using AMESCoreStudio.WebApi.Models.AMES;
using AMESCoreStudio.CommonTools.Result;
using Microsoft.Extensions.Configuration;
using System.Net;
using System.Net.Mail;
using System.Data.Common;
using System.Data;
using System.Dynamic;

namespace AMESCoreStudio.WebApi.Controllers.AMES
{
    /// <summary>
    /// 不良維修資料檔
    /// </summary>
    [Route("api/[controller]")]
    [ApiController]
    public class NgRepairsController : ControllerBase
    {
        private readonly AMESContext _context;
        private readonly IConfiguration _config;
        /// <summary>
        /// 
        /// </summary>
        /// <param name="context"></param>
        public NgRepairsController(AMESContext context)
        {
            _config = new ConfigurationBuilder().SetBasePath(Environment.CurrentDirectory).AddJsonFile("appsettings.json").Build();
            _context = context;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        // GET: api/NgRepairs
        [HttpGet]
        public async Task<ActionResult<IEnumerable<NgRepair>>> GetNgRepair()
        {
            return await _context.NgRepairs.ToListAsync();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        // GET: api/NgRepairs/5
        [HttpGet("{id}")]
        public async Task<ActionResult<IEnumerable<NgRepair>>> GetNgRepair(int id)
        {
            IQueryable<NgRepair> q = _context.NgRepairs;
            q = q.Where(p => p.RepairID.Equals(id));

            var ngRepair = await q.ToListAsync();

            if (ngRepair == null)
            {
                return NotFound();
            }

            return ngRepair;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        // GET: api/NgRepairs/5
        [HttpGet("Component/{id}")]
        public async Task<ActionResult<IEnumerable<NgRepair>>> GetNgRepairByComponent(int id)
        {
            IQueryable<NgRepair> q = _context.NgRepairs;
            q = q.Where(p => p.ComponentID.Equals(id));

            var ngRepair = await q.ToListAsync();

            if (ngRepair == null)
            {
                return NotFound();
            }

            return ngRepair;
        }

        /// <summary>
        /// 維修進/出條碼查詢
        /// </summary>
        /// <param name="stationID"></param>
        /// <param name="stateID"></param>
        /// <param name="dateStart"></param>
        /// <param name="dateEnd"></param>
        /// <param name="page"></param>
        /// <param name="limit"></param>
        /// <returns></returns>
        [Route("[action]")]
        [HttpGet]
        public async Task<ResultModel<dynamic>> GetRepairData4REP005(string stationID, string stateID, string dateStart, string dateEnd, int page = 0, int limit = 10)
        {
            Helper helper = new Helper(_context);

            ResultModel<dynamic> result = new ResultModel<dynamic>();
            var q = from q2 in _context.NgInfos
                    join q1 in _context.NgRepairs on q2.NgID equals q1.NgID into repair_data
                    from x in repair_data.DefaultIfEmpty()
                    join q3 in _context.BarcodeInfoes on q2.BarcodeID equals q3.BarcodeID
                    join q4 in _context.WipInfos on q2.WipId equals q4.WipID
                    join q5 in _context.WipAtts on q4.WipNO equals q5.WipNO
                    join q6 in _context.Stationses on q2.StationId equals q6.StationID
                    join q7 in _context.UserInfoes on x.CreateUserID equals q7.UserID into repair_user
                    from y in repair_user.DefaultIfEmpty()
                    select new
                    {
                        q3.BarcodeNo,
                        q4.WipNO,
                        q5.ModelNO,
                        q5.ItemNO,
                        q6.StationName,
                        q6.TestType,
                        TestDate = q2.CreateDate,
                        TestUserNo = helper.GetUserNo(q2.CreateUserID).Result,
                        TestUserName = helper.GetUserName(q2.CreateUserID).Result,
                        RepairUserNo = y.UserNo,
                        RepairUserName = y.UserName,
                        //RepairUserName = helper.GetUserName(y.UserID).Result,
                        q2.StationId,
                        CreateDate = (x.CreateDate == null ? null : x.CreateDate),
                        StateDesc = (x.CreateDate != null ? "出站" : "進站")
                    };
            //StateDesc= (q7.UserName == "" ? "進站" : (q7.UserName != "" ? "出站":""))
            
            q = q.Where(w => w.TestType == "F/T");

            if (stationID != null)
            {
                if (stationID != "0")
                {
                    q = q.Where(w => w.StationId == int.Parse(stationID));
                }
            }

            if (stateID != null)
            {
                if (stateID != "0")
                {
                    q = q.Where(w => w.StateDesc == "進站");
                }
            }

            if (dateStart != null && dateEnd != null)
            {
                if (dateStart != "" && dateEnd != "")
                {
                    q = q.Where(w => w.TestDate >= DateTime.Parse(dateStart) && w.TestDate <= DateTime.Parse(dateEnd).AddDays(1));
                }
            }

            q = q.OrderByDescending(w => w.TestDate);

            //紀錄筆數
            result.DataTotal = q.Count();

            //Table 頁數
            if (page > 0)
            {
                q = q.Skip((page - 1) * limit).Take(limit);
            }

            result.Data = await q.ToListAsync();

            if (result == null)
            {
                result.Msg = "查無資料";
                result.Success = false;
                return result;
            }

            result.Success = true;
            result.Msg = "OK";
            return result;
        }

        /// <summary>
        /// 維修資料統計
        /// </summary>
        /// <param name="productType"></param>
        /// <param name="testType"></param>
        /// <param name="unitNo"></param>
        /// <param name="lineID"></param>
        /// <param name="stationID"></param>
        /// <param name="wipNo"></param>
        /// <param name="itemNo"></param>
        /// <param name="dateStart"></param>
        /// <param name="dateEnd"></param>
        /// <param name="modelNo"></param>
        /// <param name="itemPN"></param>
        /// <param name="page"></param>
        /// <param name="limit"></param>
        /// <returns></returns>
        [Route("[action]")]
        [HttpGet]
        public async Task<ResultModel<dynamic>> GetRepairData4REP012Old(string productType, string testType, string unitNo, string lineID, string stationID, string wipNo, string itemNo, string dateStart, string dateEnd, string modelNo, string itemPN, int page = 0, int limit = 10)
        {
            ResultModel<dynamic> result = new ResultModel<dynamic>();
            //join -> inner join
            //join ... into ng_data from x in ng_data.DefaultIfEmpty() -> left join

            var q = from q1 in _context.NgRepairs
                    join q2 in _context.NgInfos on q1.NgID equals q2.NgID into ng_data
                    from x in ng_data.DefaultIfEmpty()
                    join q3 in _context.BarcodeInfoes on x.BarcodeID equals q3.BarcodeID into barcode_data
                    from x1 in barcode_data.DefaultIfEmpty()
                    join q4 in _context.WipInfos on x.WipId equals q4.WipID into wip_data
                    from x2 in wip_data.DefaultIfEmpty()
                    join q5 in _context.WipAtts on x2.WipNO equals q5.WipNO into att_data
                    from x3 in att_data.DefaultIfEmpty()
                    join q6 in _context.LineInfoes on x2.LineID equals q6.LineID into line_data
                    from x4 in line_data.DefaultIfEmpty()
                    join q7 in _context.Stationses on x.StationId equals q7.StationID into station_data
                    from x5 in station_data.DefaultIfEmpty()
                    join q8 in _context.NgComponents on x.NgID equals q8.NgID into ng_data2
                    from x6 in ng_data2.DefaultIfEmpty()
                    join q9 in _context.RepairResponsibleUnitses on q1.RepairResponsibleID equals q9.RRID into repair_unit
                    from b in repair_unit.DefaultIfEmpty()
                    join qa in _context.NGReasons on x6.NgNo equals qa.NGReasonNo into ng_reason
                    from x7 in ng_reason.DefaultIfEmpty()
                    join qb in _context.RepairTypes on q1.RepairTypeNo equals qb.RepairTypeNo into repair_type
                    from y in repair_type.DefaultIfEmpty()
                    join qc in _context.UserInfoes on q1.CreateUserID equals qc.UserID into user1
                    from u1 in user1.DefaultIfEmpty()
                    join qd in _context.UserInfoes on x.CreateUserID equals qd.UserID into user2
                    from u2 in user2.DefaultIfEmpty()
                    join qe in _context.TestTypes on x.TypeNo equals qe.TypeNo into test_type
                    from x8 in test_type.DefaultIfEmpty()
                    join qf in _context.UserInfoes on x6.ReplyUserID equals qf.UserID into user3
                    from u3 in user3.DefaultIfEmpty()
                    join qg in _context.RMAReasons on q1.RepairNo equals qg.RMAReasonNo into repair_reason
                    from z in repair_reason.DefaultIfEmpty()
                    join qh in _context.QATypes on z.QATypeId equals qh.QATypeID into repair_qa
                    from a in repair_qa.DefaultIfEmpty()
                    join qi in _context.CalendarTables on q1.CreateDate.Value.Date equals qi.TimeID into repair_date
                    from c in repair_date.DefaultIfEmpty()
                    select new
                    {
                        x2.UnitNO,
                        x4.LineDesc,
                        x.CreateDate,
                        c.Month,
                        c.WeekOfYearISO,
                        x5.StationName,
                        x5.TestType,
                        x2.WipNO,
                        x2.PlanQTY,
                        BarcodeNo = "'" + x1.BarcodeNo,
                        x3.ModelNO,
                        x3.ItemNO,
                        x6.SemiItemNo,
                        x6.OldPartNo,
                        x6.NewPartNo,
                        x6.NgNo,
                        ReasonDesc = x6.NgNo + '-' + x7.NGReasonDesc,
                        x6.LocationNo,
                        x6.ChangeMaterial,
                        RepairReason = q1.RepairNo + '-' + q1.RepairDesc,
                        RepairType2 = y.RepairTypeNo + '-' + y.RepairTypeDesc,
                        q1.Memo,
                        q1.RepairDesc,
                        NgType2 = x7.NGReasonNo + '-' + x7.NGReasonDesc,
                        ResponsibleUnit = b.RRID + '-' + b.RRDesc,
                        b.RRDesc,
                        u1.UserNo,
                        u1.UserName,
                        x6.ReplyDate,
                        //RepairDays = (q8.ReplyDate-q2.CreateDate).TotalDays,
                        TestDate = x.CreateDate,
                        TestUserNo = u2.UserNo,
                        TestUserName = u2.UserName,
                        TestTypeName = x8.TypeName,
                        a.QATypeName,
                        x7.NGReasonDescEn,
                        q1.PartNo,
                        x6.PinNo,
                        x6.ReelNo,
                        x6.DateCode,
                        x6.VendorCode,
                        x6.ReplyReason,
                        x6.ReplyMeasure,
                        x6.ReplyUserID,
                        ReplyUserNo = u3.UserNo,
                        ReplyUserName = u3.UserName,
                        x2.LineID,
                        x.TypeNo,
                        x.StationId,
                        q1.RepairNo,
                        x.ReasonNo,
                        x7.NGReasonDesc,
                        z.RMAReasonDesc
                    };

            if (productType != "*")
            {

            }

            if (testType != null)
            {
                if (testType != "*")
                {
                    q = q.Where(w => w.TypeNo == testType);
                }
            }

            if (unitNo != null)
            {
                if (unitNo != "*")
                {
                    q = q.Where(w => w.UnitNO == unitNo);
                }
            }

            if (lineID != null)
            {
                if (lineID != "0")
                {
                    q = q.Where(w => w.LineID == int.Parse(lineID));
                }
            }

            if (stationID != null)
            {
                if (stationID != "0")
                {
                    q = q.Where(w => w.StationId == int.Parse(stationID));
                }
            }
            if (wipNo != null)
            {
                if (wipNo != "")
                {
                    q = q.Where(w => w.WipNO == wipNo);
                }
            }

            if (itemNo != null)
            {
                if (itemNo != "")
                {
                    q = q.Where(w => w.ItemNO == itemNo);
                }
            }

            if (itemPN != null)
            {
                if (itemPN != "")
                {
                    q = q.Where(w => w.PartNo == itemPN);
                }
            }

            if (dateStart != null && dateEnd != null)
            {
                if (dateStart != "" && dateEnd != "")
                {
                    q = q.Where(w => w.CreateDate >= DateTime.Parse(dateStart) && w.CreateDate <= DateTime.Parse(dateEnd).AddDays(1));
                }
            }

            if (modelNo != null)
            {
                if (modelNo != "")
                {
                    q = q.Where(w => w.ModelNO == modelNo);
                }
            }

            q = q.Where(w => w.TestType == "F/T");

            q = q.OrderBy(w => w.CreateDate);

            //紀錄筆數
            result.DataTotal = q.Distinct().ToList().Count();

            //Table 頁數
            if (page > 0)
            {
                q = q.Distinct().Skip((page - 1) * limit).Take(limit);
            }

            result.Data = await q.Distinct().ToListAsync();

            //result.DataTotal = result.Data.Count();

            if (result == null)
            {
                result.Msg = "查無資料";
                result.Success = false;
                return result;
            }

            result.Success = true;
            result.Msg = "OK";
            return result;
        }

        /// <summary>
        /// 維修資料統計
        /// </summary>
        /// <param name="productType"></param>
        /// <param name="testType"></param>
        /// <param name="unitNo"></param>
        /// <param name="lineID"></param>
        /// <param name="stationID"></param>
        /// <param name="wipNo"></param>
        /// <param name="itemNo"></param>
        /// <param name="dateStart"></param>
        /// <param name="dateEnd"></param>
        /// <param name="modelNo"></param>
        /// <param name="itemPN"></param>
        /// <param name="page"></param>
        /// <param name="limit"></param>
        /// <returns></returns>
        [Route("[action]")]
        [HttpGet]
        public async Task<ResultModel<dynamic>> GetRepairData4REP012_New(string productType, string testType, string unitNo, string lineID, string stationID, string wipNo, string itemNo, string dateStart, string dateEnd, string modelNo, string itemPN, int page = 0, int limit = 10)
        {
            ResultModel<dynamic> result = new ResultModel<dynamic>();
            //join -> inner join
            //join ... into ng_data from x in ng_data.DefaultIfEmpty() -> left join


            var q = from q1 in _context.NgInfos
                    join q3 in _context.BarcodeInfoes on new { q1.BarcodeID, q1.Wip.WipID } equals new { q3.BarcodeID, q3.WipID }
                    join q4 in _context.WipInfos on q3.WipID equals q4.WipID
                    join q5 in _context.WipAtts on q4.WipNO equals q5.WipNO
                    join q6 in _context.LineInfoes on q4.LineID equals q6.LineID
                    join q7 in _context.Stationses on q1.StationId equals q7.StationID
                    join q8 in _context.NgComponents on q1.NgID equals q8.NgID into ng_data2
                    from x6 in ng_data2.DefaultIfEmpty()
                    join qa in _context.NGReasons on x6.NgNo equals qa.NGReasonNo into ng_reason
                    from x7 in ng_reason.DefaultIfEmpty()
                    join q2 in _context.NgRepairs on q1.NgID equals q2.NgID into ng_data
                    from x in ng_data.DefaultIfEmpty()
                    join q9 in _context.RepairResponsibleUnitses on x.RepairResponsibleID equals q9.RRID into repair_unit
                    from b in repair_unit.DefaultIfEmpty()
                    join qb in _context.RepairTypes on x.RepairTypeNo equals qb.RepairTypeNo into repair_type
                    from y in repair_type.DefaultIfEmpty()
                    join qc in _context.UserInfoes on q1.CreateUserID equals qc.UserID into user1
                    from u1 in user1.DefaultIfEmpty()
                    join qd in _context.UserInfoes on x.CreateUserID equals qd.UserID into user2
                    from u2 in user2.DefaultIfEmpty()
                    join qe in _context.TestTypes on q1.TypeNo equals qe.TypeNo into test_type
                    from x8 in test_type.DefaultIfEmpty()
                    join qf in _context.UserInfoes on x6.ReplyUserID equals qf.UserID into user3
                    from u3 in user3.DefaultIfEmpty()
                    join qg in _context.RMAReasons on x.RepairNo equals qg.RMAReasonNo into repair_reason
                    from z in repair_reason.DefaultIfEmpty()
                    join qh in _context.QATypes on z.QATypeId equals qh.QATypeID into repair_qa
                    from a in repair_qa.DefaultIfEmpty()
                    join qi in _context.CalendarTables on x.CreateDate.Value.Date equals qi.TimeID into repair_date
                    from c in repair_date.DefaultIfEmpty()
                    select new
                    {
                        q4.UnitNO,
                        q6.LineDesc,
                        q1.CreateDate,
                        c.Month,
                        c.WeekOfYearISO,
                        q7.StationName,
                        q7.TestType,
                        q4.WipNO,
                        q4.PlanQTY,
                        BarcodeNo = "'" + q3.BarcodeNo,
                        q5.ModelNO,
                        q5.ItemNO,
                        x6.SemiItemNo,
                        x6.OldPartNo,
                        x6.NewPartNo,
                        x6.NgNo,
                        ReasonDesc = x6.NgNo == null ? "" : x6.NgNo + '-' + x7.NGReasonDesc == null ? "" : x7.NGReasonDesc,
                        x6.LocationNo,
                        x6.ChangeMaterial,
                        RepairReason = (x.RepairNo == null ? "" : x.RepairNo) + '-' + (x.RepairDesc == null ? "" : x.RepairDesc),
                        RepairType2 = y.RepairTypeNo == null ? "" : y.RepairTypeNo + '-' + y.RepairTypeDesc == null ? "" : y.RepairTypeDesc,
                        x.Memo,
                        x.RepairDesc,
                        NgType2 = x7.NGReasonNo == null ? "" : x7.NGReasonNo + '-' + x7.NGReasonDesc == null ? "" : x7.NGReasonDesc,
                        //ResponsibleUnit = b.RRDesc==null?"":b.RRDesc,
                        ResponsibleUnit = b.RRID + '-' + b.RRDesc,
                        b.RRDesc,
                        u1.UserNo,
                        u1.UserName,
                        x6.ReplyDate,
                        //RepairDays = (q8.ReplyDate-q2.CreateDate).TotalDays,
                        TestDate = x.CreateDate == null ? DateTime.Now : x.CreateDate,
                        TestUserNo = u2.UserNo == null ? "" : u2.UserNo,
                        TestUserName = u2.UserName == null ? "" : u2.UserName,
                        TestTypeName = x8.TypeName == null ? "" : x8.TypeName,
                        a.QATypeName,
                        x7.NGReasonDescEn,
                        x.PartNo,
                        x6.PinNo,
                        x6.ReelNo,
                        x6.DateCode,
                        x6.VendorCode,
                        x6.ReplyReason,
                        x6.ReplyMeasure,
                        x6.ReplyUserID,
                        ReplyUserNo = u3.UserNo == null ? "" : u3.UserNo,
                        ReplyUserName = u3.UserName == null ? "" : u3.UserName,
                        q4.LineID,
                        q1.TypeNo,
                        q1.StationId,
                        x.RepairNo,
                        q1.ReasonNo,
                        x7.NGReasonDesc,
                        z.RMAReasonDesc
                    };

            if (productType != "*")
            {

            }

            if (testType != null)
            {
                if (testType != "*")
                {
                    q = q.Where(w => w.TypeNo == testType);
                }
            }

            if (unitNo != null)
            {
                if (unitNo != "*")
                {
                    q = q.Where(w => w.UnitNO == unitNo);
                }
            }

            if (lineID != null)
            {
                if (lineID != "0")
                {
                    q = q.Where(w => w.LineID == int.Parse(lineID));
                }
            }

            if (stationID != null)
            {
                if (stationID != "0")
                {
                    q = q.Where(w => w.StationId == int.Parse(stationID));
                }
            }
            if (wipNo != null)
            {
                if (wipNo != "")
                {
                    q = q.Where(w => w.WipNO == wipNo);
                }
            }

            if (itemNo != null)
            {
                if (itemNo != "")
                {
                    q = q.Where(w => w.ItemNO == itemNo);
                }
            }

            if (itemPN != null)
            {
                if (itemPN != "")
                {
                    q = q.Where(w => w.PartNo == itemPN);
                }
            }

            if (dateStart != null && dateEnd != null)
            {
                if (dateStart != "" && dateEnd != "")
                {
                    q = q.Where(w => w.CreateDate >= DateTime.Parse(dateStart) && w.CreateDate <= DateTime.Parse(dateEnd).AddDays(1));
                }
            }

            if (modelNo != null)
            {
                if (modelNo != "")
                {
                    q = q.Where(w => w.ModelNO == modelNo);
                }
            }

            q = q.Where(w => w.TestType == "F/T");

            q = q.OrderBy(w => w.CreateDate);

            //紀錄筆數
            result.DataTotal = q.Distinct().ToList().Count();

            //Table 頁數
            if (page > 0)
            {
                q = q.Distinct().Skip((page - 1) * limit).Take(limit);
            }

            result.Data = await q.Distinct().ToListAsync();

            //result.DataTotal = result.Data.Count();

            if (result == null)
            {
                result.Msg = "查無資料";
                result.Success = false;
                return result;
            }

            result.Success = true;
            result.Msg = "OK";
            return result;
        }


        /// <summary>
        /// 維修資料統計
        /// </summary>
        /// <param name="productType"></param>
        /// <param name="testType"></param>
        /// <param name="unitNo"></param>
        /// <param name="lineID"></param>
        /// <param name="stationID"></param>
        /// <param name="wipNo"></param>
        /// <param name="itemNo"></param>
        /// <param name="dateStart"></param>
        /// <param name="dateEnd"></param>
        /// <param name="modelNo"></param>
        /// <param name="itemPN"></param>
        /// <param name="page"></param>
        /// <param name="limit"></param>
        /// <returns></returns>
        [Route("[action]")]
        [HttpGet]
        public async Task<ResultModel<dynamic>> GetRepairData4REP012(string productType, string testType, string unitNo, string lineID, string stationID, string wipNo, string itemNo, string dateStart, string dateEnd, string modelNo, string itemPN, int page = 0, int limit = 10)
        {
            ResultModel<dynamic> result = new ResultModel<dynamic>();
            //join -> inner join
            //join ... into ng_data from x in ng_data.DefaultIfEmpty() -> left join

            var q = from q1 in _context.NgInfos
                    join q3 in _context.BarcodeInfoes on  q1.BarcodeID  equals  q3.BarcodeID  into barcode_data
                    from x1 in barcode_data.DefaultIfEmpty()
                    join q4 in _context.WipInfos on q1.WipId equals q4.WipID into wip_data
                    from x2 in wip_data.DefaultIfEmpty()
                    join q5 in _context.WipAtts on x2.WipNO equals q5.WipNO into att_data
                    from x3 in att_data.DefaultIfEmpty()
                    join q6 in _context.LineInfoes on x2.LineID equals q6.LineID into line_data
                    from x4 in line_data.DefaultIfEmpty()
                    join q7 in _context.Stationses on q1.StationId equals q7.StationID into station_data
                    from x5 in station_data.DefaultIfEmpty()
                    join q8 in _context.NgComponents on q1.NgID equals q8.NgID into ng_data2
                    from x6 in ng_data2.DefaultIfEmpty()
                    join qa in _context.NGReasons on x6.NgNo equals qa.NGReasonNo into ng_reason
                    from x7 in ng_reason.DefaultIfEmpty()
                    join q2 in _context.NgRepairs on q1.NgID equals q2.NgID into ng_data
                    from x in ng_data.DefaultIfEmpty()
                    join q9 in _context.RepairResponsibleUnitses on x.RepairResponsibleID equals q9.RRID into repair_unit
                    from b in repair_unit.DefaultIfEmpty()
                    join qb in _context.RepairTypes on x.RepairTypeNo equals qb.RepairTypeNo into repair_type
                    from y in repair_type.DefaultIfEmpty()
                    join qc in _context.UserInfoes on q1.CreateUserID equals qc.UserID into user1
                    from u1 in user1.DefaultIfEmpty()
                    join qd in _context.UserInfoes on x.CreateUserID equals qd.UserID into user2
                    from u2 in user2.DefaultIfEmpty()
                    join qe in _context.TestTypes on q1.TypeNo equals qe.TypeNo into test_type
                    from x8 in test_type.DefaultIfEmpty()
                    join qf in _context.UserInfoes on x6.ReplyUserID equals qf.UserID into user3
                    from u3 in user3.DefaultIfEmpty()
                    join qg in _context.RMAReasons on x.RepairNo equals qg.RMAReasonNo into repair_reason
                    from z in repair_reason.DefaultIfEmpty()
                    join qh in _context.QATypes on z.QATypeId equals qh.QATypeID into repair_qa
                    from a in repair_qa.DefaultIfEmpty()
                    join qi in _context.CalendarTables on x.CreateDate.Value.Date equals qi.TimeID into repair_date
                    from c in repair_date.DefaultIfEmpty()
                    select new
                    {
                        x2.UnitNO,
                        x4.LineDesc,
                        q1.CreateDate,
                        c.Month,
                        c.WeekOfYearISO,
                        x5.StationName,
                        x5.TestType,
                        x2.WipNO,
                        x2.PlanQTY,
                        BarcodeNo = "'" + x1.BarcodeNo,
                        x3.ModelNO,
                        x3.ItemNO,
                        x6.SemiItemNo,
                        x6.OldPartNo,
                        x6.NewPartNo,
                        x6.NgNo,
                        ReasonDesc = x6.NgNo == null ? "" : x6.NgNo + '-' + x7.NGReasonDesc == null ? "" : x7.NGReasonDesc,
                        x6.LocationNo,
                        x6.ChangeMaterial,
                        RepairReason = (x.RepairNo == null ? "" : x.RepairNo) + '-' + (x.RepairDesc == null ? "" : x.RepairDesc),
                        RepairType2 = y.RepairTypeNo == null ? "" : y.RepairTypeNo + '-' + y.RepairTypeDesc == null ? "" : y.RepairTypeDesc,
                        x.Memo,
                        x.RepairDesc,
                        NgType2 = x7.NGReasonNo == null ? "" : x7.NGReasonNo + '-' + x7.NGReasonDesc == null ? "" : x7.NGReasonDesc,
                        //ResponsibleUnit = b.RRDesc==null?"":b.RRDesc,
                        ResponsibleUnit = b.RRID + '-' + b.RRDesc,
                        b.RRDesc,
                        u1.UserNo,
                        u1.UserName,
                        x6.ReplyDate,
                        //RepairDays = (q8.ReplyDate-q2.CreateDate).TotalDays,
                        TestDate = x.CreateDate == null ? DateTime.Now : x.CreateDate,
                        TestUserNo = u2.UserNo == null ? "" : u2.UserNo,
                        TestUserName = u2.UserName == null ? "" : u2.UserName,
                        TestTypeName = x8.TypeName == null ? "" : x8.TypeName,
                        a.QATypeName,
                        x7.NGReasonDescEn,
                        x.PartNo,
                        x6.PinNo,
                        x6.ReelNo,
                        x6.DateCode,
                        x6.VendorCode,
                        x6.ReplyReason,
                        x6.ReplyMeasure,
                        x6.ReplyUserID,
                        ReplyUserNo = u3.UserNo == null ? "" : u3.UserNo,
                        ReplyUserName = u3.UserName == null ? "" : u3.UserName,
                        x2.LineID,
                        q1.TypeNo,
                        q1.StationId,
                        x.RepairNo,
                        q1.ReasonNo,
                        x7.NGReasonDesc,
                        z.RMAReasonDesc
                    };

            if (productType != "*")
            {

            }

            if (testType != null)
            {
                if (testType != "*")
                {
                    q = q.Where(w => w.TypeNo == testType);
                }
            }

            if (unitNo != null)
            {
                if (unitNo != "*")
                {
                    q = q.Where(w => w.UnitNO == unitNo);
                }
            }

            if (lineID != null)
            {
                if (lineID != "0")
                {
                    q = q.Where(w => w.LineID == int.Parse(lineID));
                }
            }

            if (stationID != null)
            {
                if (stationID != "0")
                {
                    q = q.Where(w => w.StationId == int.Parse(stationID));
                }
            }
            if (wipNo != null)
            {
                if (wipNo != "")
                {
                    q = q.Where(w => w.WipNO == wipNo);
                }
            }

            if (itemNo != null)
            {
                if (itemNo != "")
                {
                    q = q.Where(w => w.ItemNO == itemNo);
                }
            }

            if (itemPN != null)
            {
                if (itemPN != "")
                {
                    q = q.Where(w => w.PartNo == itemPN);
                }
            }

            if (dateStart != null && dateEnd != null)
            {
                if (dateStart != "" && dateEnd != "")
                {
                    q = q.Where(w => w.CreateDate >= DateTime.Parse(dateStart) && w.CreateDate <= DateTime.Parse(dateEnd).AddDays(1));
                }
            }

            if (modelNo != null)
            {
                if (modelNo != "")
                {
                    q = q.Where(w => w.ModelNO == modelNo);
                }
            }

            //q = q.Where(w => w.TestType == "F/T");

            q = q.OrderBy(w => w.CreateDate);

            //紀錄筆數
            result.DataTotal = q.Distinct().ToList().Count();

            //Table 頁數
            if (page > 0)
            {
                q = q.Distinct().Skip((page - 1) * limit).Take(limit);
            }

            result.Data = await q.Distinct().ToListAsync();

            //result.DataTotal = result.Data.Count();

            if (result == null)
            {
                result.Msg = "查無資料";
                result.Success = false;
                return result;
            }

            result.Success = true;
            result.Msg = "OK";
            return result;
        }


        /// <summary>
        /// 不良明細統計
        /// </summary>
        /// <param name="productType"></param>
        /// <param name="testType"></param>
        /// <param name="unitNo"></param>
        /// <param name="lineID"></param>
        /// <param name="stationID"></param>
        /// <param name="wipNo"></param>
        /// <param name="itemNo"></param>
        /// <param name="dateStart"></param>
        /// <param name="dateEnd"></param>
        /// <param name="modelNo"></param>
        /// <param name="page"></param>
        /// <param name="limit"></param>
        /// <returns></returns>
        [Route("[action]")]
        [HttpGet]
        public async Task<ResultModel<dynamic>> GetNgData4QRS019(string productType, string testType, string unitNo, string lineID, string stationID, string wipNo, string itemNo, string dateStart, string dateEnd, string modelNo, int page = 0, int limit = 10)
        {
            ResultModel<dynamic> result = new ResultModel<dynamic>();
            var q = from q1 in _context.NgInfos 
                    join q2 in _context.NgComponents on q1.NgID equals q2.NgID
                    join q3 in _context.BarcodeInfoes on q1.BarcodeID equals q3.BarcodeID
                    join q4 in _context.WipInfos on q1.WipId equals q4.WipID
                    join q5 in _context.WipAtts on q4.WipNO equals q5.WipNO
                    join q6 in _context.LineInfoes on q4.LineID equals q6.LineID
                    join q7 in _context.Stationses on q1.StationId equals q7.StationID
                    join q8 in _context.NGReasons on q2.NgNo equals q8.NGReasonNo
                    join q9 in _context.TestTypes on q1.TypeNo equals q9.TypeNo
                    join qi in _context.CalendarTables on q1.CreateDate.Date equals qi.TimeID
                    select new
                    {
                        q1.CreateDate,
                        qi.TimeID,
                        q4.UnitNO,
                        q4.CustomerNO,
                        q5.ItemNO,
                        q5.ModelNO,
                        q4.WipNO,
                        q6.LineDesc,
                        q2.NgNo,
                        q8.NGReasonDesc,
                        q2.LocationNo,
                        qi.Month,
                        qi.WeekOfYearISO,
                        q7.StationName,
                        q4.LineID,
                        q1.TypeNo,
                        q1.StationId,
                        BarcodeNo = "'" + q3.BarcodeNo
                    };

            if (productType != "*")
            {

            }

            if (testType != null)
            {
                if (testType != "*")
                {
                    q = q.Where(w => w.TypeNo == testType);
                }
            }

            if (unitNo != null)
            {
                if (unitNo != "*")
                {
                    q = q.Where(w => w.UnitNO == unitNo);
                }
            }

            if (lineID != null)
            {
                if (lineID != "0")
                {
                    q = q.Where(w => w.LineID == int.Parse(lineID));
                }
            }

            if (stationID != null)
            {
                if (stationID != "0")
                {
                    q = q.Where(w => w.StationId == int.Parse(stationID));
                }
            }
            if (wipNo != null)
            {
                if (wipNo != "")
                {
                    q = q.Where(w => w.WipNO == wipNo);
                }
            }

            if (itemNo != null)
            {
                if (itemNo != "")
                {
                    q = q.Where(w => w.ItemNO == itemNo);
                }
            }

            if (dateStart != null && dateEnd != null)
            {
                if (dateStart != "" && dateEnd != "")
                {
                    q = q.Where(w => w.CreateDate >= DateTime.Parse(dateStart) && w.CreateDate <= DateTime.Parse(dateEnd).AddDays(1));
                }
            }

            if (modelNo != null)
            {
                if (modelNo != "")
                {
                    q = q.Where(w => w.ModelNO == modelNo);
                }
            }

            q = q.OrderBy(w => w.CreateDate);

            var g = q.GroupBy(x => new { x.TimeID, x.CustomerNO,x.ItemNO,x.WipNO,x.LocationNo,x.NgNo,x.NGReasonDesc}).Select(x => new
            {
                CreateDate = x.Key.TimeID,
                CustomerNO = x.Key.ItemNO.Substring(0,2),
                ItemNO = x.Key.ItemNO,
                WipNO = x.Key.WipNO,
                LocationNo = x.Key.LocationNo,
                NgNo = x.Key.NgNo,
                NGReasonDesc = x.Key.NGReasonDesc,
                NGQty = x.Count()
            });

            //紀錄筆數
            result.DataTotal = g.Count();

            //Table 頁數
            if (page > 0)
            {
                g = g.Skip((page - 1) * limit).Take(limit);
            }

            result.Data = await g.ToListAsync();

            if (result == null)
            {
                result.Msg = "查無資料";
                result.Success = false;
                return result;
            }

            result.Success = true;
            result.Msg = "OK";
            return result;
        }


        /// <summary>
        /// 不良明細統計
        /// </summary>
        /// <param name="wipNo"></param>
        /// <param name="lineDesc"></param>
        /// <param name="stationID"></param>
        /// <param name="dateStart"></param>
        /// <param name="dateEnd"></param>
        /// <returns></returns>
        [Route("[action]")]
        [HttpGet]
        public async Task<ResultModel<dynamic>> GetNgData4QRS010(string wipNo,string lineDesc, string stationID, string dateStart, string dateEnd)
        {
            ResultModel<dynamic> result = new ResultModel<dynamic>();
            var q = from q1 in _context.NgInfos
                    join q2 in _context.NgComponents on q1.NgID equals q2.NgID
                    join q3 in _context.BarcodeInfoes on q1.BarcodeID equals q3.BarcodeID
                    join q4 in _context.WipInfos on q1.WipId equals q4.WipID
                    join q5 in _context.WipAtts on q4.WipNO equals q5.WipNO
                    join q6 in _context.LineInfoes on q4.LineID equals q6.LineID
                    join q7 in _context.Stationses on q1.StationId equals q7.StationID
                    join q8 in _context.NGReasons on q2.NgNo equals q8.NGReasonNo
                    join q9 in _context.TestTypes on q1.TypeNo equals q9.TypeNo
                    join qi in _context.CalendarTables on q1.CreateDate.Date equals qi.TimeID
                    select new
                    {
                        q1.CreateDate,
                        qi.TimeID,
                        q4.UnitNO,
                        q4.CustomerNO,
                        q5.ItemNO,
                        q5.ModelNO,
                        q4.WipNO,
                        q6.LineDesc,
                        q2.NgNo,
                        q8.NGReasonDesc,
                        q2.LocationNo,
                        qi.Month,
                        qi.WeekOfYearISO,
                        q7.StationName,
                        q4.LineID,
                        q1.TypeNo,
                        q1.StationId,
                        BarcodeNo = "" + q3.BarcodeNo
                    };

            if (wipNo != null)
            {
                if (wipNo != "")
                {
                    q = q.Where(w => w.WipNO == wipNo);
                }
            }

            if (lineDesc != null)
            {
                if (lineDesc != "")
                {
                    q = q.Where(w => w.LineDesc == lineDesc);
                }
            }

            if (stationID != null)
            {
                if (stationID != "0")
                {
                    q = q.Where(w => w.StationId == int.Parse(stationID));
                }
            }

            if (dateStart != null && dateEnd != null)
            {
                if (dateStart != "" && dateEnd != "")
                {
                    q = q.Where(w => w.CreateDate >= DateTime.Parse(dateStart) && w.CreateDate <= DateTime.Parse(dateEnd).AddDays(1));
                }
            }

            q = q.OrderBy(w => w.CreateDate);


            //紀錄筆數
            result.DataTotal = q.Count();

            result.Data = await q.ToListAsync();

            if (result == null)
            {
                result.Msg = "查無資料";
                result.Success = false;
                return result;
            }

            result.Success = true;
            result.Msg = "OK";
            return result;
        }


        /// <summary>
        /// 維修進/出統計報表
        /// </summary>
        /// <param name="wipNo"></param>
        /// <param name="itemNo"></param>
        /// <param name="dateStart"></param>
        /// <param name="dateEnd"></param>
        /// <param name="page"></param>
        /// <param name="limit"></param>
        /// <returns></returns>
        [Route("[action]")]
        [HttpGet]
        public async Task<ResultModel<dynamic>> GetRepairData4REP013(string wipNo, string itemNo, string dateStart, string dateEnd, int page = 0, int limit = 10)
        {
            Helper helper = new Helper(_context);

            ResultModel<dynamic> result = new ResultModel<dynamic>();
            var q = from q2 in _context.NgInfos
                    join q1 in _context.NgRepairs on q2.NgID equals q1.NgID into repair_data
                    from x in repair_data.DefaultIfEmpty()
                    join q3 in _context.BarcodeInfoes on q2.BarcodeID equals q3.BarcodeID
                    join q4 in _context.WipInfos on q2.WipId equals q4.WipID
                    join q5 in _context.WipAtts on q4.WipNO equals q5.WipNO
                    join q6 in _context.LineInfoes on q4.LineID equals q6.LineID
                    join q7 in _context.Stationses on q2.StationId equals q7.StationID
                    join q8 in _context.NgComponents on q2.NgID equals q8.NgID
                    join q9 in _context.RepairResponsibleUnitses on x.RepairResponsibleID equals q9.RRID into repair_unit
                    from b in repair_unit.DefaultIfEmpty()
                    join qa in _context.NGReasons on q8.NgNo equals qa.NGReasonNo
                    join qb in _context.RepairTypes on x.RepairTypeNo equals qb.RepairTypeNo into repair_type
                    from y in repair_type.DefaultIfEmpty()
                    join qe in _context.TestTypes on q2.TypeNo equals qe.TypeNo
                    join qg in _context.RMAReasons on x.RepairNo equals qg.RMAReasonNo into repair_reason
                    from z in repair_reason.DefaultIfEmpty()
                    join qh in _context.QATypes on z.QATypeId equals qh.QATypeID into repair_qa
                    from a in repair_qa.DefaultIfEmpty()
                    join qi in _context.CalendarTables on x.CreateDate.Value.Date equals qi.TimeID into repair_date
                    from c in repair_date.DefaultIfEmpty()
                    select new
                    {
                        q4.UnitNO,
                        q6.LineDesc,
                        CreateDate = (x.CreateDate == null ? null : x.CreateDate),
                        c.Month,
                        WeekOfYearISO = (c.WeekOfYearISO == null ? 0 : c.WeekOfYearISO),
                        q7.StationName,
                        q7.TestType,
                        q4.WipNO,
                        q4.PlanQTY,
                        q3.BarcodeNo,
                        q5.ModelNO,
                        q5.ItemNO,
                        q8.SemiItemNo,
                        q8.OldPartNo,
                        q8.NewPartNo,
                        q8.NgNo,
                        ReasonDesc = q8.NgNo + '-' + qa.NGReasonDesc,
                        q8.LocationNo,
                        q8.ChangeMaterial,
                        RepairReason = x.RepairNo + '-' + x.RepairDesc,
                        RepairType2 = y.RepairTypeNo + '-' + y.RepairTypeDesc,
                        x.Memo,
                        x.RepairDesc,
                        NgType2 = qa.NGReasonNo + '-' + qa.NGReasonDesc,
                        ResponsibleUnit = b.RRID + '-' + b.RRDesc,
                        b.RRDesc,
                        UserNo = helper.GetUserNo(x.CreateUserID).Result,
                        UserName = helper.GetUserName(x.CreateUserID).Result,
                        q8.ReplyDate,
                        //RepairDays = (q8.ReplyDate-q2.CreateDate).TotalDays,
                        TestDate = q2.CreateDate,
                        TestUserNo = helper.GetUserNo(q2.CreateUserID).Result,
                        TestUserName = helper.GetUserName(x.CreateUserID).Result,
                        TestTypeName = qe.TypeName,
                        a.QATypeName,
                        qa.NGReasonDescEn,
                        x.PartNo,
                        q8.PinNo,
                        q8.ReelNo,
                        q8.DateCode,
                        q8.VendorCode,
                        q8.ReplyReason,
                        q8.ReplyMeasure,
                        q8.ReplyUserID,
                        ReplyUserNo = helper.GetUserNo(q8.CreateUserID).Result,
                        ReplyUserName = helper.GetUserName(q8.CreateUserID).Result,
                        q4.LineID,
                        q2.TypeNo,
                        q2.StationId,
                        x.RepairNo,
                        q2.ReasonNo,
                        CheckInDate = q2.CreateDate,
                        CheckInUserNo = helper.GetUserNo(q2.CreateUserID).Result,
                        CheckInUserName = helper.GetUserName(q2.CreateUserID).Result,
                        CheckOutUserNo = helper.GetUserNo(x.CreateUserID).Result,
                        CheckOutUserName = helper.GetUserName(x.CreateUserID).Result,
                        CheckOutDate = (x.CreateDate == null ? null : x.CreateDate),
                        //TAT = EF.Functions.DateDiffDay(q2.CreateDate, x.CreateDate == null ? DateTime.Now : x.CreateDate),
                        TAT = (x.CreateDate == null ? DateTime.Now : x.CreateDate).Value.Subtract(q2.CreateDate).TotalDays.ToString("0.00"),
                        StateDesc = (x.CreateDate != null ? "出站" : "進站")
                    };

            if (wipNo != null)
            {
                if (wipNo != "")
                {
                    q = q.Where(w => w.WipNO == wipNo);
                }
            }

            if (itemNo != null)
            {
                if (itemNo != "")
                {
                    q = q.Where(w => w.ItemNO == itemNo);
                }
            }

            if (dateStart != null && dateEnd != null)
            {
                if (dateStart != "" && dateEnd != "")
                {
                    q = q.Where(w => w.CreateDate >= DateTime.Parse(dateStart) && w.CreateDate <= DateTime.Parse(dateEnd).AddDays(1));
                }
            }

            //q = q.Where(w => w.TestType == "F/T");

            string[] unit_list = new string[] { "I","T"};

            q = q.Where(w => unit_list.Contains(w.UnitNO));

            q = q.OrderByDescending(w => w.CheckInDate);

            //紀錄筆數
            //result.DataTotal = q.Count();
            result.DataTotal = q.Distinct().ToList().Count();

            //Table 頁數
            if (page > 0)
            {
                q = q.Distinct().Skip((page - 1) * limit).Take(limit);
            }

            result.Data = await q.Distinct().ToListAsync();

            if (result == null)
            {
                result.Msg = "查無資料";
                result.Success = false;
                return result;
            }

            result.Success = true;
            result.Msg = "OK";
            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="reader"></param>
        /// <returns></returns>
        public static DataTable DataReaderToDataTable(DbDataReader reader)
        {
            try
            {
                DataTable dt = new DataTable();
                int fieldCount = reader.FieldCount;
                for (int fieldIndex = 0; fieldIndex < fieldCount; ++fieldIndex)
                {
                    dt.Columns.Add(reader.GetName(fieldIndex), reader.GetFieldType(fieldIndex));
                }

                dt.BeginLoadData();

                object[] rowValues = new object[fieldCount];
                while (reader.Read())
                {
                    reader.GetValues(rowValues);
                    dt.LoadDataRow(rowValues, true);
                }
                reader.Close();
                dt.EndLoadData();

                return dt;

            }
            catch (Exception ex)
            {
                throw new Exception("DataReader Convert DataTable Error!", ex);
            }
        }

        /// <summary>
        /// 根據工單統計不良代碼
        /// </summary>
        /// <param name="wipNo"></param>
        /// <returns></returns>
        [Route("[action]")]
        [HttpGet]
        public async Task<ResultModel<dynamic>> GetErrorCode4QRS018(string wipNo)
        {
            ResultModel<dynamic> result = new ResultModel<dynamic>();

            /*
            var q = from a in _context.NgInfos
                    join b in _context.NgComponents on a.NgID equals b.NgID
                    join c in _context.Stationses on a.StationId equals c.StationID
                    join d in _context.WipInfos on a.WipId equals d.WipID
                    join e in _context.NGReasons on b.NgNo equals e.NGReasonNo
                    select new
                    {
                        a.WipId,
                        d.WipNO,
                        a.StationId,
                        c.StationName,
                        b.NgNo,
                        e.NGReasonDesc,
                        a.BarcodeID,
                        a.CreateDate
                    };

            if (wipNo != null)
            {
                if (wipNo != "")
                {
                    q = q.Where(w => w.WipNO == wipNo);
                }
            }

            q = q.OrderBy(w => w.CreateDate).Distinct();

            var g = q.GroupBy(x => new { x.WipId, x.WipNO, x.StationId, x.StationName, x.NgNo, x.NGReasonDesc }).Select(x => new
            {
                WipID = x.Key.WipId,
                WipNO = x.Key.WipNO,
                StationId = x.Key.StationId,
                StationName = x.Key.StationName,
                NgNo = x.Key.NgNo,
                NGReasonDesc = x.Key.NGReasonDesc,
                NgQty = x.Count()
            });

            //紀錄筆數
            result.DataTotal = g.Count();

            result.Data = await g.ToListAsync();
            */
            string sql = string.Format(@"select x.*,y.total_qty,round(x.ng_qty * 100 / y.total_qty,2) as rate from (
select a.wip_id,e.wip_no,b.ng_no,d.ng_reason_desc,a.station_id,c.station_name,count(distinct a.barcode_id) as ng_qty
from jhames.ng_info a,jhames.ng_component b, jhames.stations c, jhames.ng_reason d, jhames.wip_info e
where a.ng_id = b.ng_id and b.ng_no = d.ng_reason_no and a.station_id = c.station_id and a.wip_id = e.wip_id and e.wip_no = '{0}'
group by a.wip_id,e.wip_no,b.ng_no,d.ng_reason_desc,a.station_id,c.station_name) x,
(
select wip_id, sum(ng_qty) as total_qty from(
 select a.wip_id, e.wip_no, b.ng_no, d.ng_reason_desc, a.station_id, c.station_name, count(distinct a.barcode_id) as ng_qty
 from jhames.ng_info a, jhames.ng_component b, jhames.stations c, jhames.ng_reason d, jhames.wip_info e
 where a.ng_id = b.ng_id and b.ng_no = d.ng_reason_no and a.station_id = c.station_id and a.wip_id = e.wip_id and e.wip_no = '{0}'
 group by a.wip_id, e.wip_no, b.ng_no, d.ng_reason_desc, a.station_id, c.station_name)
group by wip_id) y
where x.wip_id = y.wip_id", wipNo);

            DbConnection conn = _context.Database.GetDbConnection();
            if (conn.State != System.Data.ConnectionState.Open)
            {
                await conn.OpenAsync();
            }

            using (var cmd = conn.CreateCommand())
            {
                cmd.CommandText = sql;

                using (var reader = await cmd.ExecuteReaderAsync())
                {
                    if (reader.HasRows)
                    {
                        List<dynamic> list = new List<dynamic>();
                        DataTable table = new DataTable();

                        table = DataReaderToDataTable(reader);

                        foreach (DataRow row in table.Rows)
                        {
                            dynamic dyn = new ExpandoObject();
                            list.Add(dyn);
                            foreach (DataColumn column in table.Columns)
                            {
                                var dic = (IDictionary<string, object>)dyn;
                                dic[column.ColumnName] = row[column];
                            }
                        }

                        result.DataTotal = list.Count();
                        result.Data = list;
                    }
                }
            }

            if (result == null)
            {
                result.Msg = "查無資料";
                result.Success = false;
                return result;
            }

            result.Success = true;
            result.Msg = "OK";
            return result;
        }

        /// <summary>
        /// 根據工單統計維修代碼
        /// </summary>
        /// <param name="wipNo"></param>
        /// <returns></returns>
        [Route("[action]")]
        [HttpGet]
        public async Task<ResultModel<dynamic>> GetRepairCode4QRS018(string wipNo)
        {
            ResultModel<dynamic> result = new ResultModel<dynamic>();
            string sql = string.Format(@"select x.*,y.total_qty,round(x.rma_qty * 100 / y.total_qty,2) as rate from (
select a.wip_id,e.wip_no,b.repair_no,d.rma_reason_desc,a.station_id,c.station_name,count(distinct a.barcode_id) as rma_qty
from jhames.ng_info a,jhames.ng_repair b,jhames.stations c,jhames.rma_reason d,jhames.wip_info e
where a.ng_id = b.ng_id and b.repair_no = d.rma_reason_no and a.station_id = c.station_id and a.wip_id = e.wip_id and e.wip_no = '{0}'
group by a.wip_id,e.wip_no,b.repair_no,d.rma_reason_desc,a.station_id,c.station_name) x,
(
select wip_id,sum(rma_qty) as total_qty from (
select a.wip_id,e.wip_no,b.repair_no,d.rma_reason_desc,a.station_id,c.station_name,count(distinct a.barcode_id) as rma_qty
from jhames.ng_info a,jhames.ng_repair b,jhames.stations c,jhames.rma_reason d,jhames.wip_info e
where a.ng_id = b.ng_id and b.repair_no = d.rma_reason_no and a.station_id = c.station_id and a.wip_id = e.wip_id and e.wip_no = '{0}'
group by a.wip_id,e.wip_no,b.repair_no,d.rma_reason_desc,a.station_id,c.station_name)
group by wip_id) y
where x.wip_id = y.wip_id", wipNo);

            DbConnection conn = _context.Database.GetDbConnection();
            if (conn.State != System.Data.ConnectionState.Open)
            {
                await conn.OpenAsync();
            }

            using (var cmd = conn.CreateCommand())
            {
                cmd.CommandText = sql;

                using (var reader = await cmd.ExecuteReaderAsync())
                {
                    if (reader.HasRows)
                    {
                        List<dynamic> list = new List<dynamic>();
                        DataTable table = new DataTable();

                        table = DataReaderToDataTable(reader);

                        foreach (DataRow row in table.Rows)
                        {
                            dynamic dyn = new ExpandoObject();
                            list.Add(dyn);
                            foreach (DataColumn column in table.Columns)
                            {
                                var dic = (IDictionary<string, object>)dyn;
                                dic[column.ColumnName] = row[column];
                            }
                        }

                        result.DataTotal = list.Count();
                        result.Data = list;
                    }
                }
            }

            if (result == null)
            {
                result.Msg = "查無資料";
                result.Success = false;
                return result;
            }

            result.Success = true;
            result.Msg = "OK";
            return result;
        }

        /// <summary>
        /// 根據工單統計維修料號
        /// </summary>
        /// <param name="wipNo"></param>
        /// <returns></returns>
        [Route("[action]")]
        [HttpGet]
        public async Task<ResultModel<dynamic>> GetRepairPartNo4QRS018(string wipNo)
        {
            ResultModel<dynamic> result = new ResultModel<dynamic>();
            string sql = string.Format(@"select x.*, y.total_qty, round(x.part_qty * 100 / y.total_qty, 2) as rate from(
select a.wip_id, e.wip_no, b.part_no, a.station_id, c.station_name, count(distinct a.barcode_id) as part_qty
from jhames.ng_info a, jhames.ng_repair b, jhames.stations c, jhames.wip_info e
where a.ng_id = b.ng_id and a.station_id = c.station_id and a.wip_id = e.wip_id and e.wip_no = '{0}'
group by a.wip_id, e.wip_no, b.part_no, a.station_id, c.station_name) x,
(
select wip_id, sum(part_qty) as total_qty from(
select a.wip_id, e.wip_no, b.part_no, a.station_id, c.station_name, count(distinct a.barcode_id) as part_qty
from jhames.ng_info a, jhames.ng_repair b, jhames.stations c, jhames.wip_info e
where a.ng_id = b.ng_id and a.station_id = c.station_id and a.wip_id = e.wip_id and e.wip_no = '{0}'
group by a.wip_id, e.wip_no, b.part_no, a.station_id, c.station_name)
group by wip_id) y
where x.wip_id = y.wip_id", wipNo);

            DbConnection conn = _context.Database.GetDbConnection();
            if (conn.State != System.Data.ConnectionState.Open)
            {
                await conn.OpenAsync();
            }

            using (var cmd = conn.CreateCommand())
            {
                cmd.CommandText = sql;

                using (var reader = await cmd.ExecuteReaderAsync())
                {
                    if (reader.HasRows)
                    {
                        List<dynamic> list = new List<dynamic>();
                        DataTable table = new DataTable();

                        table = DataReaderToDataTable(reader);

                        foreach (DataRow row in table.Rows)
                        {
                            dynamic dyn = new ExpandoObject();
                            list.Add(dyn);
                            foreach (DataColumn column in table.Columns)
                            {
                                var dic = (IDictionary<string, object>)dyn;
                                dic[column.ColumnName] = row[column];
                            }
                        }

                        result.DataTotal = list.Count();
                        result.Data = list;
                    }
                }
            }

            if (result == null)
            {
                result.Msg = "查無資料";
                result.Success = false;
                return result;
            }

            result.Success = true;
            result.Msg = "OK";
            return result;
        }

        /// <summary>
        /// 根據工單+站別+b不良代碼查詢不良條碼明細
        /// </summary>
        /// <param name="wipNo"></param>
        /// <param name="stationID"></param>
        /// <param name="ngNo"></param>
        /// <returns></returns>
        [Route("[action]")]
        [HttpGet]
        public async Task<ResultModel<dynamic>> GetErrorCodeList4QRS018(string wipNo, int stationID, string ngNo)
        {
            ResultModel<dynamic> result = new ResultModel<dynamic>();
            string sql = string.Format(@"select distinct c.barcode_no,e.station_name,b.ng_no,g.ng_reason_desc,b.location_no,b.reply_reason,f.user_name,a.create_date
from jhames.ng_info a,jhames.ng_component b,jhames.barcode_info c,jhames.wip_info d,jhames.stations e,jhsys.user_info f,jhames.ng_reason g
where a.ng_id = b.ng_id and a.barcode_id = c.barcode_id and c.wip_id = d.wip_id and a.station_id = e.station_id and b.create_userid = f.user_id(+)
and b.ng_no = g.ng_reason_no and d.wip_no = '{0}' and a.station_id={1} and b.ng_no='{2}'", wipNo, stationID, ngNo);

            DbConnection conn = _context.Database.GetDbConnection();
            if (conn.State != System.Data.ConnectionState.Open)
            {
                await conn.OpenAsync();
            }

            using (var cmd = conn.CreateCommand())
            {
                cmd.CommandText = sql;

                using (var reader = await cmd.ExecuteReaderAsync())
                {
                    if (reader.HasRows)
                    {
                        List<dynamic> list = new List<dynamic>();
                        DataTable table = new DataTable();

                        table = DataReaderToDataTable(reader);

                        foreach (DataRow row in table.Rows)
                        {
                            dynamic dyn = new ExpandoObject();
                            list.Add(dyn);
                            foreach (DataColumn column in table.Columns)
                            {
                                var dic = (IDictionary<string, object>)dyn;
                                dic[column.ColumnName] = row[column];
                            }
                        }

                        result.DataTotal = list.Count();
                        result.Data = list;
                    }
                }
            }

            if (result == null)
            {
                result.Msg = "查無資料";
                result.Success = false;
                return result;
            }

            result.Success = true;
            result.Msg = "OK";
            return result;
        }

        /// <summary>
        /// 根據工單+站別+維修代碼查詢維修條碼明細
        /// </summary>
        /// <param name="wipNo"></param>
        /// <param name="stationID"></param>
        /// <param name="repairNo"></param>
        /// <returns></returns>
        [Route("[action]")]
        [HttpGet]
        public async Task<ResultModel<dynamic>> GetRepairCodeList4QRS018(string wipNo, int stationID, string repairNo)
        {
            ResultModel<dynamic> result = new ResultModel<dynamic>();
            string sql = string.Format(@"select distinct c.barcode_no,e.station_name,b.repair_no,g.rma_reason_desc,b.part_no,f.user_name,a.create_date,b.memo 
from jhames.ng_info a,jhames.ng_repair b,jhames.barcode_info c,jhames.wip_info d,jhames.stations e,jhsys.user_info f,jhames.rma_reason g
where a.ng_id = b.ng_id and a.barcode_id = c.barcode_id and c.wip_id = d.wip_id and a.station_id = e.station_id and b.create_userid = f.user_id(+)
and b.repair_no = g.rma_reason_no and d.wip_no = '{0}' and a.station_id={1} and b.repair_no='{2}'", wipNo, stationID, repairNo);

            DbConnection conn = _context.Database.GetDbConnection();
            if (conn.State != System.Data.ConnectionState.Open)
            {
                await conn.OpenAsync();
            }

            using (var cmd = conn.CreateCommand())
            {
                cmd.CommandText = sql;

                using (var reader = await cmd.ExecuteReaderAsync())
                {
                    if (reader.HasRows)
                    {
                        List<dynamic> list = new List<dynamic>();
                        DataTable table = new DataTable();

                        table = DataReaderToDataTable(reader);

                        foreach (DataRow row in table.Rows)
                        {
                            dynamic dyn = new ExpandoObject();
                            list.Add(dyn);
                            foreach (DataColumn column in table.Columns)
                            {
                                var dic = (IDictionary<string, object>)dyn;
                                dic[column.ColumnName] = row[column];
                            }
                        }

                        result.DataTotal = list.Count();
                        result.Data = list;
                    }
                }
            }

            if (result == null)
            {
                result.Msg = "查無資料";
                result.Success = false;
                return result;
            }

            result.Success = true;
            result.Msg = "OK";
            return result;
        }

        /// <summary>
        /// 根據工單+站別+料號查詢維修條碼明細
        /// </summary>
        /// <param name="wipNo"></param>
        /// <param name="stationID"></param>
        /// <param name="partNo"></param>
        /// <returns></returns>
        [Route("[action]")]
        [HttpGet]
        public async Task<ResultModel<dynamic>> GetRepairPartNoList4QRS018(string wipNo,int stationID,string partNo)
        {
            ResultModel<dynamic> result = new ResultModel<dynamic>();
            string sql = string.Format(@"select distinct c.barcode_no,e.station_name,b.repair_no,b.repair_desc,b.part_no,f.user_name,a.create_date,b.memo 
from jhames.ng_info a,jhames.ng_repair b,jhames.barcode_info c,jhames.wip_info d,jhames.stations e,jhsys.user_info f
where a.ng_id = b.ng_id and a.barcode_id = c.barcode_id and a.wip_id = d.wip_id and a.station_id = e.station_id and b.create_userid = f.user_id(+)
and d.wip_no = '{0}' and a.station_id={1} and b.part_no='{2}'", wipNo, stationID, partNo);

            DbConnection conn = _context.Database.GetDbConnection();
            if (conn.State != System.Data.ConnectionState.Open)
            {
                await conn.OpenAsync();
            }

            using (var cmd = conn.CreateCommand())
            {
                cmd.CommandText = sql;

                using (var reader = await cmd.ExecuteReaderAsync())
                {
                    if (reader.HasRows)
                    {
                        List<dynamic> list = new List<dynamic>();
                        DataTable table = new DataTable();

                        table = DataReaderToDataTable(reader);

                        foreach (DataRow row in table.Rows)
                        {
                            dynamic dyn = new ExpandoObject();
                            list.Add(dyn);
                            foreach (DataColumn column in table.Columns)
                            {
                                var dic = (IDictionary<string, object>)dyn;
                                dic[column.ColumnName] = row[column];
                            }
                        }

                        result.DataTotal = list.Count();
                        result.Data = list;
                    }
                }
            }

            if (result == null)
            {
                result.Msg = "查無資料";
                result.Success = false;
                return result;
            }

            result.Success = true;
            result.Msg = "OK";
            return result;
        }

        /// <summary>
        /// 維修資料統計by不良代碼
        /// </summary>
        /// <param name="productType"></param>
        /// <param name="testType"></param>
        /// <param name="unitNo"></param>
        /// <param name="lineID"></param>
        /// <param name="stationID"></param>
        /// <param name="wipNo"></param>
        /// <param name="itemNo"></param>
        /// <param name="dateStart"></param>
        /// <param name="dateEnd"></param>
        /// <param name="modelNo"></param>
        /// <param name="itemPN"></param>
        /// <returns></returns>
        [Route("[action]")]
        [HttpGet]
        public async Task<ResultModel<dynamic>> GetErrorCode4REP012(string productType, string testType, string unitNo, string lineID, string stationID, string wipNo, string itemNo, string dateStart, string dateEnd, string modelNo,string itemPN)
        {
            ResultModel<dynamic> result = new ResultModel<dynamic>();
            var q = from q1 in _context.NgRepairs
                    join q2 in _context.NgInfos on q1.NgID equals q2.NgID
                    join q3 in _context.BarcodeInfoes on q2.BarcodeID equals q3.BarcodeID
                    join q4 in _context.WipInfos on q2.WipId equals q4.WipID
                    join q5 in _context.WipAtts on q4.WipNO equals q5.WipNO
                    join q6 in _context.LineInfoes on q4.LineID equals q6.LineID
                    join q7 in _context.Stationses on q2.StationId equals q7.StationID
                    join q8 in _context.NgComponents on q2.NgID equals q8.NgID
                    join q9 in _context.RepairResponsibleUnitses on q1.RepairResponsibleID equals q9.RRID
                    select new
                    {
                        q4.UnitNO,
                        q6.LineDesc,
                        q1.CreateDate,
                        q7.StationName,
                        q4.WipNO,
                        q5.ItemNO,
                        q5.ModelNO,
                        q4.LineID,
                        q3.BarcodeNo,
                        q2.TypeNo,
                        q2.StationId,
                        q2.ReasonNo,
                        q1.RepairNo,
                        q1.RepairTypeNo,
                        q1.RepairDesc,
                        q1.PartNo,
                        q8.LocationNo,
                        q9.RRDesc
                    };
            if (productType != "*")
            {

            }

            if (testType != null)
            {
                if (testType != "*")
                {
                    q = q.Where(w => w.TypeNo == testType);
                }
            }

            if (unitNo != null)
            {
                if (unitNo != "*")
                {
                    q = q.Where(w => w.UnitNO == unitNo);
                }
            }

            if (lineID != null)
            {
                if (lineID != "0")
                {
                    q = q.Where(w => w.LineID == int.Parse(lineID));
                }
            }

            if (stationID != null)
            {
                if (stationID != "0")
                {
                    q = q.Where(w => w.StationId == int.Parse(lineID));
                }
            }
            if (wipNo != null)
            {
                if (wipNo != "")
                {
                    q = q.Where(w => w.WipNO == wipNo);
                }
            }

            if (itemNo != null)
            {
                if (itemNo != "")
                {
                    q = q.Where(w => w.ItemNO == itemNo);
                }
            }

            if (itemPN != null)
            {
                if (itemPN != "")
                {
                    q = q.Where(w => w.PartNo == itemPN);
                }
            }

            if (dateStart != null && dateEnd != null)
            {
                if (dateStart != "" && dateEnd != "")
                {
                    q = q.Where(w => w.CreateDate >= DateTime.Parse(dateStart) && w.CreateDate <= DateTime.Parse(dateEnd).AddDays(1));
                }
            }

            if (modelNo != null)
            {
                if (modelNo != "")
                {
                    q = q.Where(w => w.ModelNO == modelNo);
                }
            }

            q = q.OrderBy(w => w.CreateDate);

            var g = q.GroupBy(x => new { x.ReasonNo }).Select(x => new 
            {
                ErrorCode = x.Key.ReasonNo,
                ErrorQty = x.Count()
            });

            //紀錄筆數
            result.DataTotal = g.Count();

            result.Data = await g.ToListAsync();

            if (result == null)
            {
                result.Msg = "查無資料";
                result.Success = false;
                return result;
            }

            result.Success = true;
            result.Msg = "OK";
            return result;
        }

        /// <summary>
        /// 維修資料統計by維修代碼
        /// </summary>
        /// <param name="productType"></param>
        /// <param name="testType"></param>
        /// <param name="unitNo"></param>
        /// <param name="lineID"></param>
        /// <param name="stationID"></param>
        /// <param name="wipNo"></param>
        /// <param name="itemNo"></param>
        /// <param name="dateStart"></param>
        /// <param name="dateEnd"></param>
        /// <param name="modelNo"></param>
        /// <param name="itemPN"></param>
        /// <returns></returns>
        [Route("[action]")]
        [HttpGet]
        public async Task<ResultModel<dynamic>> GetRMACode4REP012(string productType, string testType, string unitNo, string lineID, string stationID, string wipNo, string itemNo, string dateStart, string dateEnd, string modelNo,string itemPN)
        {
            ResultModel<dynamic> result = new ResultModel<dynamic>();
            var q = from q1 in _context.NgRepairs
                    join q2 in _context.NgInfos on q1.NgID equals q2.NgID
                    join q3 in _context.BarcodeInfoes on q2.BarcodeID equals q3.BarcodeID
                    join q4 in _context.WipInfos on q2.WipId equals q4.WipID
                    join q5 in _context.WipAtts on q4.WipNO equals q5.WipNO
                    join q6 in _context.LineInfoes on q4.LineID equals q6.LineID
                    join q7 in _context.Stationses on q2.StationId equals q7.StationID
                    join q8 in _context.NgComponents on q2.NgID equals q8.NgID
                    join q9 in _context.RepairResponsibleUnitses on q1.RepairResponsibleID equals q9.RRID
                    select new
                    {
                        q4.UnitNO,
                        q6.LineDesc,
                        q1.CreateDate,
                        q7.StationName,
                        q4.WipNO,
                        q5.ItemNO,
                        q5.ModelNO,
                        q4.LineID,
                        q3.BarcodeNo,
                        q2.TypeNo,
                        q2.StationId,
                        q2.ReasonNo,
                        q1.RepairNo,
                        q1.RepairTypeNo,
                        q1.RepairDesc,
                        q1.PartNo,
                        q8.LocationNo,
                        q9.RRDesc
                    };
            if (productType != "*")
            {

            }

            if (testType != null)
            {
                if (testType != "*")
                {
                    q = q.Where(w => w.TypeNo == testType);
                }
            }

            if (unitNo != null)
            {
                if (unitNo != "*")
                {
                    q = q.Where(w => w.UnitNO == unitNo);
                }
            }

            if (lineID != null)
            {
                if (lineID != "0")
                {
                    q = q.Where(w => w.LineID == int.Parse(lineID));
                }
            }

            if (stationID != null)
            {
                if (stationID != "0")
                {
                    q = q.Where(w => w.StationId == int.Parse(lineID));
                }
            }
            if (wipNo != null)
            {
                if (wipNo != "")
                {
                    q = q.Where(w => w.WipNO == wipNo);
                }
            }

            if (itemNo != null)
            {
                if (itemNo != "")
                {
                    q = q.Where(w => w.ItemNO == itemNo);
                }
            }

            if (itemPN != null)
            {
                if (itemPN != "")
                {
                    q = q.Where(w => w.PartNo == itemPN);
                }
            }

            if (dateStart != null && dateEnd != null)
            {
                if (dateStart != "" && dateEnd != "")
                {
                    q = q.Where(w => w.CreateDate >= DateTime.Parse(dateStart) && w.CreateDate <= DateTime.Parse(dateEnd).AddDays(1));
                }
            }

            if (modelNo != null)
            {
                if (modelNo != "")
                {
                    q = q.Where(w => w.ModelNO == modelNo);
                }
            }

            q = q.OrderBy(w => w.CreateDate);

            var g = q.GroupBy(x => new { x.RepairNo }).Select(x => new
            {
                RMACode = x.Key.RepairNo,
                RMAQty = x.Count()
            });

            //紀錄筆數
            result.DataTotal = g.Count();

            result.Data = await g.ToListAsync();

            if (result == null)
            {
                result.Msg = "查無資料";
                result.Success = false;
                return result;
            }

            result.Success = true;
            result.Msg = "OK";
            return result;
        }


        /// <summary>
        /// 維修資料統計by維修位置
        /// </summary>
        /// <param name="productType"></param>
        /// <param name="testType"></param>
        /// <param name="unitNo"></param>
        /// <param name="lineID"></param>
        /// <param name="stationID"></param>
        /// <param name="wipNo"></param>
        /// <param name="itemNo"></param>
        /// <param name="dateStart"></param>
        /// <param name="dateEnd"></param>
        /// <param name="modelNo"></param>
        /// <param name="itemPN"></param>
        /// <returns></returns>
        [Route("[action]")]
        [HttpGet]
        public async Task<ResultModel<dynamic>> GetLocation4REP012(string productType, string testType, string unitNo, string lineID, string stationID, string wipNo, string itemNo, string dateStart, string dateEnd, string modelNo,string itemPN)
        {
            ResultModel<dynamic> result = new ResultModel<dynamic>();
            var q = from q1 in _context.NgRepairs
                    join q2 in _context.NgInfos on q1.NgID equals q2.NgID
                    join q3 in _context.BarcodeInfoes on q2.BarcodeID equals q3.BarcodeID
                    join q4 in _context.WipInfos on q2.WipId equals q4.WipID
                    join q5 in _context.WipAtts on q4.WipNO equals q5.WipNO
                    join q6 in _context.LineInfoes on q4.LineID equals q6.LineID
                    join q7 in _context.Stationses on q2.StationId equals q7.StationID
                    join q8 in _context.NgComponents on q2.NgID equals q8.NgID
                    join q9 in _context.RepairResponsibleUnitses on q1.RepairResponsibleID equals q9.RRID
                    select new
                    {
                        q4.UnitNO,
                        q6.LineDesc,
                        q1.CreateDate,
                        q7.StationName,
                        q4.WipNO,
                        q5.ItemNO,
                        q5.ModelNO,
                        q4.LineID,
                        q3.BarcodeNo,
                        q2.TypeNo,
                        q2.StationId,
                        q2.ReasonNo,
                        q1.RepairNo,
                        q1.RepairTypeNo,
                        q1.RepairDesc,
                        q1.PartNo,
                        q8.LocationNo,
                        q9.RRDesc
                    };
            if (productType != "*")
            {

            }

            if (testType != null)
            {
                if (testType != "*")
                {
                    q = q.Where(w => w.TypeNo == testType);
                }
            }

            if (unitNo != null)
            {
                if (unitNo != "*")
                {
                    q = q.Where(w => w.UnitNO == unitNo);
                }
            }

            if (lineID != null)
            {
                if (lineID != "0")
                {
                    q = q.Where(w => w.LineID == int.Parse(lineID));
                }
            }

            if (stationID != null)
            {
                if (stationID != "0")
                {
                    q = q.Where(w => w.StationId == int.Parse(lineID));
                }
            }
            if (wipNo != null)
            {
                if (wipNo != "")
                {
                    q = q.Where(w => w.WipNO == wipNo);
                }
            }

            if (itemNo != null)
            {
                if (itemNo != "")
                {
                    q = q.Where(w => w.ItemNO == itemNo);
                }
            }

            if (itemPN != null)
            {
                if (itemPN != "")
                {
                    q = q.Where(w => w.PartNo == itemPN);
                }
            }

            if (dateStart != null && dateEnd != null)
            {
                if (dateStart != "" && dateEnd != "")
                {
                    q = q.Where(w => w.CreateDate >= DateTime.Parse(dateStart) && w.CreateDate <= DateTime.Parse(dateEnd).AddDays(1));
                }
            }

            if (modelNo != null)
            {
                if (modelNo != "")
                {
                    q = q.Where(w => w.ModelNO == modelNo);
                }
            }

            q = q.OrderBy(w => w.CreateDate);

            var g = q.GroupBy(x => new { x.LocationNo }).Select(x => new
            {
                LocationNo = x.Key.LocationNo,
                LocationQty = x.Count()
            });

            //紀錄筆數
            result.DataTotal = g.Count();

            result.Data = await g.ToListAsync();

            if (result == null)
            {
                result.Msg = "查無資料";
                result.Success = false;
                return result;
            }

            result.Success = true;
            result.Msg = "OK";
            return result;
        }


        /// <summary>
        /// 維修資料統計by責任單位
        /// </summary>
        /// <param name="productType"></param>
        /// <param name="testType"></param>
        /// <param name="unitNo"></param>
        /// <param name="lineID"></param>
        /// <param name="stationID"></param>
        /// <param name="wipNo"></param>
        /// <param name="itemNo"></param>
        /// <param name="dateStart"></param>
        /// <param name="dateEnd"></param>
        /// <param name="modelNo"></param>
        /// <param name="itemPN"></param>
        /// <returns></returns>
        [Route("[action]")]
        [HttpGet]
        public async Task<ResultModel<dynamic>> GetRepairResponsibleUnit4REP012(string productType, string testType, string unitNo, string lineID, string stationID, string wipNo, string itemNo, string dateStart, string dateEnd, string modelNo,string itemPN)
        {
            ResultModel<dynamic> result = new ResultModel<dynamic>();
            var q = from q1 in _context.NgRepairs
                    join q2 in _context.NgInfos on q1.NgID equals q2.NgID
                    join q3 in _context.BarcodeInfoes on q2.BarcodeID equals q3.BarcodeID
                    join q4 in _context.WipInfos on q2.WipId equals q4.WipID
                    join q5 in _context.WipAtts on q4.WipNO equals q5.WipNO
                    join q6 in _context.LineInfoes on q4.LineID equals q6.LineID
                    join q7 in _context.Stationses on q2.StationId equals q7.StationID
                    join q8 in _context.NgComponents on q2.NgID equals q8.NgID
                    join q9 in _context.RepairResponsibleUnitses on q1.RepairResponsibleID equals q9.RRID
                    select new
                    {
                        q4.UnitNO,
                        q6.LineDesc,
                        q1.CreateDate,
                        q7.StationName,
                        q4.WipNO,
                        q5.ItemNO,
                        q5.ModelNO,
                        q4.LineID,
                        q3.BarcodeNo,
                        q2.TypeNo,
                        q2.StationId,
                        q2.ReasonNo,
                        q1.RepairNo,
                        q1.RepairTypeNo,
                        q1.RepairDesc,
                        q1.PartNo,
                        q8.LocationNo,
                        q9.RRDesc
                    };
            if (productType != "*")
            {

            }

            if (testType != null)
            {
                if (testType != "*")
                {
                    q = q.Where(w => w.TypeNo == testType);
                }
            }

            if (unitNo != null)
            {
                if (unitNo != "*")
                {
                    q = q.Where(w => w.UnitNO == unitNo);
                }
            }

            if (lineID != null)
            {
                if (lineID != "0")
                {
                    q = q.Where(w => w.LineID == int.Parse(lineID));
                }
            }

            if (stationID != null)
            {
                if (stationID != "0")
                {
                    q = q.Where(w => w.StationId == int.Parse(lineID));
                }
            }
            if (wipNo != null)
            {
                if (wipNo != "")
                {
                    q = q.Where(w => w.WipNO == wipNo);
                }
            }

            if (itemNo != null)
            {
                if (itemNo != "")
                {
                    q = q.Where(w => w.ItemNO == itemNo);
                }
            }

            if (itemPN != null)
            {
                if (itemPN != "")
                {
                    q = q.Where(w => w.PartNo == itemPN);
                }
            }

            if (dateStart != null && dateEnd != null)
            {
                if (dateStart != "" && dateEnd != "")
                {
                    q = q.Where(w => w.CreateDate >= DateTime.Parse(dateStart) && w.CreateDate <= DateTime.Parse(dateEnd).AddDays(1));
                }
            }

            if (modelNo != null)
            {
                if (modelNo != "")
                {
                    q = q.Where(w => w.ModelNO == modelNo);
                }
            }

            q = q.OrderBy(w => w.CreateDate);

            var g = q.GroupBy(x => new { x.RRDesc }).Select(x => new
            {
                RRDesc = x.Key.RRDesc,
                RRDescQty = x.Count()
            });

            //紀錄筆數
            result.DataTotal = g.Count();

            result.Data = await g.ToListAsync();

            if (result == null)
            {
                result.Msg = "查無資料";
                result.Success = false;
                return result;
            }

            result.Success = true;
            result.Msg = "OK";
            return result;
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        /// <param name="ngRepair"></param>
        /// <returns></returns>
        // PUT: api/NgRepairs/5
        // To protect from overposting attacks, enable the specific properties you want to bind to, for
        // more details, see https://go.microsoft.com/fwlink/?linkid=2123754.
        [HttpPut("{id}")]
        public async Task<ResultModel<NgRepair>> PutNgRepair(int id, NgRepair ngRepair)
        {
            ResultModel<NgRepair> result = new ResultModel<NgRepair>();

            if (id != ngRepair.RepairID)
            {
                result.Success = false;
                result.Msg = "不良維修ID錯誤";
                return result;
            }

            _context.Entry(ngRepair).State = EntityState.Modified;
            _context.Entry(ngRepair).Property(p => p.CreateUserID).IsModified = false;

            try
            {
                await _context.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!NgRepairExists(id))
                {
                    result.Success = false;
                    result.Msg = "不良維修ID不存在";
                    return result;
                }
                else
                {
                    throw;
                }
            }

            result.Success = true;
            result.Msg = "OK";
            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="mail_from"></param>
        /// <param name="mail_to"></param>
        /// <param name="mail_subject"></param>
        /// <param name="mail_body"></param>
        /// <param name="mail_server"></param>
        /// <param name="mail_port"></param>
        /// <param name="mail_user"></param>
        /// <param name="mail_password"></param>
        /// <returns></returns>
        [HttpPost("Mail")]
        public async Task<ResultModel<dynamic>> PostMailTest(string mail_from, string mail_to, string mail_subject,string mail_body, string mail_server, int mail_port,string mail_user, string mail_password)
        {
            ResultModel<dynamic> result = new ResultModel<dynamic>();

            string mailSubject = mail_subject;
            string mailBody = mail_body;

            MailMessage mesMail = new MailMessage();
            mesMail.From = new MailAddress(mail_from);
            mesMail.To.Add(new MailAddress(mail_to));
            mesMail.Subject = mailSubject;
            mesMail.SubjectEncoding = System.Text.Encoding.UTF8;
            mesMail.Body = mailBody;
            mesMail.IsBodyHtml = true;
            mesMail.BodyEncoding = System.Text.Encoding.UTF8;

            SmtpClient mailClient = new SmtpClient(mail_server,mail_port);

            //mailClient.EnableSsl = true;
            NetworkCredential nc = new NetworkCredential();
            nc.UserName = mail_user;
            nc.Password = mail_password;
            mailClient.Credentials = nc;

            mailClient.Send(mesMail);

            result.Success = true;
            result.Msg = "OK";
            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="ngRepair"></param>
        /// <returns></returns>
        // POST: api/NgRepairs
        // To protect from overposting attacks, enable the specific properties you want to bind to, for
        // more details, see https://go.microsoft.com/fwlink/?linkid=2123754.
        [HttpPost]
        public async Task<ResultModel<NgRepair>> PostNgRepair(NgRepair ngRepair)
        {
            ResultModel<NgRepair> result = new ResultModel<NgRepair>();

            Helper helper = new Helper(_context);
            ngRepair.RepairID = helper.GetIDKey("REPAIR_ID").Result;

            _context.NgRepairs.Add(ngRepair);
            try
            {
                await _context.SaveChangesAsync();
            }
            catch (DbUpdateException)
            {
                if (NgRepairExists(ngRepair.RepairID))
                {
                    result.Success = false;
                    result.Msg = "不良維修ID重複";
                    return result;
                }
                else
                {
                    throw;
                }
            }

            //判断预警
            var q1 = from a in _context.NgRepairs
                     join b in _context.NgInfos on a.NgID equals b.NgID
                     join c in _context.BarcodeInfoes on b.BarcodeID equals c.BarcodeID
                     join d in _context.WipInfos on c.WipID equals d.WipID
                     select new
                     {
                         a.NgID,
                         d.WipNO
                     };

            q1 = q1.Where(w => w.NgID.Equals(ngRepair.NgID));

            var data1 = await q1.ToListAsync();

            string wip_no = data1[0].WipNO;

            var q2 = from a in _context.NgRepairs
                     join b in _context.NgInfos on a.NgID equals b.NgID
                     join c in _context.BarcodeInfoes on b.BarcodeID equals c.BarcodeID
                     join d in _context.WipInfos on c.WipID equals d.WipID
                     join e in _context.WipAtts on d.WipNO equals e.WipNO
                     join f in _context.RMAReasons on a.RepairNo equals f.RMAReasonNo
                     join g in _context.Stationses on b.StationId equals g.StationID
                     join h in _context.UserInfoes on a.CreateUserID equals h.UserID
                     select new
                     {
                         a.NgID,
                         d.WipNO,
                         d.WerksNO,
                         c.BarcodeNo,
                         g.StationName,
                         a.CreateDate,
                         h.UserName,
                         a.RepairNo,
                         f.RMAReasonDesc,
                         e.ItemNO,
                         e.ModelNO
                     };

            q2 = q2.Where(w => w.WipNO.Equals(wip_no));
            q2 = q2.Where(w => w.RepairNo.Equals(ngRepair.RepairNo));

            var data2 = await q2.ToListAsync();

            if (data2.Count > 3)
            {
                try
                {
                    string itemNo2 = data2[0].ItemNO;
                    string modelNo2 = data2[0].ModelNO;
                    string repairDesc = data2[0].RMAReasonDesc;
                    string werksNo = data2[0].WerksNO;

                    //保存警报资料
                    string alarmDesc = string.Format("維修代碼{0}:{2}累積超過{1}次", ngRepair.RepairNo, data2.Count, repairDesc);

                    WipAlarm wipAlarm = new WipAlarm();
                    wipAlarm.WipAlarmID = helper.GetIDKey("WIP_ALARMID").Result;
                    wipAlarm.AlarmTypeID = 3;
                    wipAlarm.WipNO = wip_no;
                    wipAlarm.AlarmParam = ngRepair.RepairNo;
                    wipAlarm.AlarmValue = data2.Count.ToString();
                    wipAlarm.AlarmDesc = alarmDesc;
                    wipAlarm.AlarmDateTime = DateTime.Now;

                    _context.WipAlarms.Add(wipAlarm);
                    await _context.SaveChangesAsync();

                    //发送警报资料
                    string webSiteUrl = _config["WebSiteUrl"].ToString();
                    string viewUrl = webSiteUrl + "/QRS/QRS018A/" + wip_no;

                    //2023-08-20 BB.Wang Modify
                    //工單號碼 + (工程編號) + - +  異常原因;
                    //string mailSubject = "警報持續郵件" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                    string mailSubject = wip_no + " (" + itemNo2 + ")" + " - " + alarmDesc;

                    string mailBody = "";
                    mailBody = mailBody + "警報工單:" + wip_no + ",廠別:" + werksNo + ",工程編號:" + itemNo2 + ",機種:" + modelNo2 + "<br />";
                    mailBody = mailBody + "警報時間:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "<br />";
                    mailBody = mailBody + "警報原因:" + alarmDesc + "<br />";
                    //mailBody = mailBody + "警報鏈接:" + webSiteUrl + "/QRS/QRS012/" + wip_no + "<br />";
                    mailBody = mailBody + "警報鏈接:<a href='" + viewUrl + "'>" + viewUrl + "</a><br />";
                    mailBody = mailBody + "詳細資訊:<br />";

                    string tableData = "";
                    tableData = tableData + "<table border = '1' width='100%' cellspacing='2px' cellpadding='10px'>";
                    tableData = tableData + "<tr bgcolor='#66CCFF' height='30'><td>生產序號</td><td>發生站別</td><td>維修代碼</td><td>維修描述</td><td>發生時間</td><td>作業人員</td></tr>";
                    for (int i = 0; i < data2.Count; i++)
                    {
                        string lineData = "<tr height='30'><td>" + data2[i].BarcodeNo + "</td><td>" + data2[i].StationName + "</td><td>" + data2[i].RepairNo + "</td><td>" + data2[i].RMAReasonDesc + "</td><td>" + data2[i].CreateDate.Value.ToString("yyyy-MM-dd HH:mm:ss") + "</td><td>" + data2[i].UserName + "</td></tr>";
                        tableData = tableData + lineData;

                    }
                    tableData = tableData + "</table>";

                    mailBody = mailBody + tableData;

                    string mailFrom = _config["MailFrom"].ToString();
                    //string mailTo = _config["MailTo"].ToString();
                    string mailSmtpServer = _config["MailSmtpServer"].ToString();
                    int mailSmtpPort = int.Parse(_config["MailSmtpPort"].ToString());
                    string mailUser = _config["MailUser"].ToString();
                    string mailPassword = _config["MailUserPassword"].ToString();

                    MailMessage mesMail = new MailMessage();
                    mesMail.From = new MailAddress(mailFrom);

                    IQueryable<MailGroup> q3 = _context.MailGroups;
                    q3 = q3.Where(p => p.GroupNo.Equals("WIP_ALARM"));
                    var mail1 = await q3.ToListAsync();

                    if(mail1.Count>0)
                    {
                        var q4 = from a in _context.MailGroups
                                 join b in _context.MailGroupDetails on a.GroupID equals b.GroupID
                                 join c in _context.UserInfoes on b.UserID equals c.UserID
                                 select new
                                 {
                                     a.GroupID,
                                     b.UserID,
                                     c.UserEMail
                                 };

                        q4 = q4.Where(w => w.GroupID.Equals(mail1[0].GroupID));

                        var mail2 = await q4.ToListAsync();
                        if (mail2.Count>0)
                        {
                            for (int i = 0; i < mail2.Count; i++)
                            {
                                mesMail.To.Add(new MailAddress(mail2[i].UserEMail));
                            }
                        }

                        //mesMail.To.Add(new MailAddress(mailTo));

                        mesMail.Subject = mailSubject;
                        mesMail.SubjectEncoding = System.Text.Encoding.UTF8;
                        mesMail.Body = mailBody;
                        mesMail.IsBodyHtml = true;
                        mesMail.BodyEncoding = System.Text.Encoding.UTF8;

                        SmtpClient mailClient = new SmtpClient(mailSmtpServer, mailSmtpPort);

                        //mailClient.EnableSsl = true;
                        NetworkCredential nc = new NetworkCredential();
                        nc.UserName = mailUser;
                        nc.Password = mailPassword;
                        mailClient.Credentials = nc;

                        mailClient.Send(mesMail);

                    }
                }
                catch { }

            }

            var q_part_no = from a in _context.NgRepairs
                     join b in _context.NgInfos on a.NgID equals b.NgID
                     join c in _context.BarcodeInfoes on b.BarcodeID equals c.BarcodeID
                     join d in _context.WipInfos on c.WipID equals d.WipID
                     join e in _context.WipAtts on d.WipNO equals e.WipNO
                     join f in _context.Stationses on b.StationId equals f.StationID
                     join g in _context.UserInfoes on a.CreateUserID equals g.UserID
                     select new
                     {
                         a.NgID,
                         d.WipNO,
                         d.WerksNO,
                         c.BarcodeNo,
                         f.StationName,
                         g.UserName,
                         a.CreateDate,
                         a.PartNo,
                         e.ItemNO,
                         e.ModelNO
                     };

            q_part_no = q_part_no.Where(w => w.WipNO.Equals(wip_no));
            q_part_no = q_part_no.Where(w => w.PartNo.Equals(ngRepair.PartNo));

            var data3 = await q_part_no.ToListAsync();

            if (data3.Count > 5)
            {
                try
                {
                    string itemNo3 = data3[0].ItemNO;
                    string modelNo3 = data3[0].ModelNO;
                    string werksNo = data3[0].WerksNO;

                    //保存警报资料
                    string alarmDesc = string.Format("維修料號{0}累積超過{1}次", ngRepair.PartNo, data3.Count);

                    WipAlarm wipAlarm = new WipAlarm();
                    wipAlarm.WipAlarmID = helper.GetIDKey("WIP_ALARMID").Result;
                    wipAlarm.AlarmTypeID = 3;
                    wipAlarm.WipNO = wip_no;
                    wipAlarm.AlarmParam = ngRepair.PartNo;
                    wipAlarm.AlarmValue = data3.Count.ToString();
                    wipAlarm.AlarmDesc = alarmDesc;
                    wipAlarm.AlarmDateTime = DateTime.Now;

                    _context.WipAlarms.Add(wipAlarm);
                    await _context.SaveChangesAsync();


                    //发送警报资料
                    string webSiteUrl = _config["WebSiteUrl"].ToString();
                    string viewUrl = webSiteUrl + "/QRS/QRS018A/" + wip_no;

                    //2023-08-20 BB.Wang Modify
                    //工單號碼 + (工程編號) + - +  異常原因;
                    //string mailSubject = "警報持續郵件" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                    string mailSubject = wip_no + " (" + itemNo3 + ")" + " - " + alarmDesc;

                    string mailBody = "";
                    //mailBody = mailBody + "警報工單:" + wip_no + "<br />";
                    mailBody = mailBody + "警報工單:" + wip_no + ",廠別:" + werksNo + ",工程編號:" + itemNo3 + ",機種:" + modelNo3 + "<br />";
                    mailBody = mailBody + "警報時間:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "<br />";
                    mailBody = mailBody + "警報原因:" + alarmDesc + "<br />";
                    //mailBody = mailBody + "警報鏈接:" + webSiteUrl + "/QRS/QRS012/" + wip_no + "<br />";
                    mailBody = mailBody + "警報鏈接:<a href='" + viewUrl + "'>" + viewUrl + "</a><br />";

                    mailBody = mailBody + "詳細資訊:<br />";

                    string tableData = "";
                    tableData = tableData + "<table border = '1' width='100%' cellspacing='2px' cellpadding='10px'>";
                    tableData = tableData + "<tr bgcolor='#66CCFF' height='30'><td>生產序號</td><td>發生站別</td><td>維修料號</td><td>發生時間</td><td>作業人員</td></tr>";
                    for (int i = 0; i < data3.Count; i++)
                    {
                        string lineData = "<tr height='30'><td>" + data3[i].BarcodeNo + "</td><td>" + data3[i].StationName + "</td><td>" + data3[i].PartNo + "</td><td>" + data3[i].CreateDate.Value.ToString("yyyy-MM-dd HH:mm:ss") + "</td><td>" + data3[i].UserName + "</td></tr>";
                        tableData = tableData + lineData;

                    }
                    tableData = tableData + "</table>";

                    mailBody = mailBody + tableData;

                    string mailFrom = _config["MailFrom"].ToString();
                    //string mailTo = _config["MailTo"].ToString();
                    string mailSmtpServer = _config["MailSmtpServer"].ToString();
                    int mailSmtpPort = int.Parse(_config["MailSmtpPort"].ToString());
                    string mailUser = _config["MailUser"].ToString();
                    string mailPassword = _config["MailUserPassword"].ToString();

                    MailMessage mesMail = new MailMessage();
                    mesMail.From = new MailAddress(mailFrom);

                    IQueryable<MailGroup> q3 = _context.MailGroups;
                    q3 = q3.Where(p => p.GroupNo.Equals("WIP_ALARM"));
                    var mail1 = await q3.ToListAsync();

                    if (mail1.Count > 0)
                    {
                        var q4 = from a in _context.MailGroups
                                 join b in _context.MailGroupDetails on a.GroupID equals b.GroupID
                                 join c in _context.UserInfoes on b.UserID equals c.UserID
                                 select new
                                 {
                                     a.GroupID,
                                     b.UserID,
                                     c.UserEMail
                                 };

                        q4 = q4.Where(w => w.GroupID.Equals(mail1[0].GroupID));

                        var mail2 = await q4.ToListAsync();
                        if (mail2.Count > 0)
                        {
                            for (int i = 0; i < mail2.Count; i++)
                            {
                                mesMail.To.Add(new MailAddress(mail2[i].UserEMail));
                            }
                        }

                        //mesMail.To.Add(new MailAddress(mailTo));

                        mesMail.Subject = mailSubject;
                        mesMail.SubjectEncoding = System.Text.Encoding.UTF8;
                        mesMail.Body = mailBody;
                        mesMail.IsBodyHtml = true;
                        mesMail.BodyEncoding = System.Text.Encoding.UTF8;

                        SmtpClient mailClient = new SmtpClient(mailSmtpServer, mailSmtpPort);

                        //mailClient.EnableSsl = true;
                        NetworkCredential nc = new NetworkCredential();
                        nc.UserName = mailUser;
                        nc.Password = mailPassword;
                        mailClient.Credentials = nc;

                        mailClient.Send(mesMail);

                    }
                }
                catch { }

            }

            result.Success = true;
            result.Msg = "OK" + "-" + ngRepair.RepairID;
            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        // DELETE: api/NgRepairs/5
        [HttpDelete("{id}")]
        public async Task<ResultModel<NgRepair>> DeleteNgRepair(decimal id)
        {
            ResultModel<NgRepair> result = new ResultModel<NgRepair>();

            var ngRepair = await _context.NgRepairs.FindAsync(id);
            if (ngRepair == null)
            {
                result.Success = false;
                result.Msg = "不良維修ID不存在";
                return result;
            }

            _context.NgRepairs.Remove(ngRepair);
            await _context.SaveChangesAsync();

            result.Success = true;
            result.Msg = "OK";
            return result;
        }

        private bool NgRepairExists(decimal id)
        {
            return _context.NgRepairs.Any(e => e.RepairID == id);
        }
    }
}