using System; using System.Data.SqlTypes; using System.Collections; using System.Linq; using System.Data.Linq; using System.Xml; using System.IO; using ICSSoft.Base.Config.AppConfig; using System.Collections.Specialized; using ICSSoft.Frame.Helper; using ICSSoft.Frame.Data.Entity; using ICSSoft.Frame.DataConnect.Action; namespace ICSSoft.Frame.DataConnect { /// /// ReportHelper 的摘要说明。 /// public class ReportHelper { private const string OutLineResource = "OUTLINERESOURCE"; private FramDataContext _domainDataProvider = null; // public ReportHelper() // { // } public ReportHelper(FramDataContext domainDataProvider) { this._domainDataProvider = domainDataProvider; } public FramDataContext DataProvider { get { return _domainDataProvider; } } public int WeekOfYear(string Date) { int weekOfYear =0; String sqlWeek = "select datepart(week,'"+Date+"') "; var query = this.DataProvider.ExecuteQuery(sqlWeek); weekOfYear = query.First(); if (weekOfYear > 0) { return weekOfYear; } else { weekOfYear = 1; } return weekOfYear; } private static void DecodeDateWeek(DateTime dt,out int year,out int weekOfYear,out int dayOfWeek) { int dayOfYear = dt.DayOfYear; int monthOfYear = dt.Month; year = dt.Year; dayOfWeek = (int)dt.DayOfWeek; DateTime startDate = new DateTime(dt.Year,1,1); System.DayOfWeek startDayOfWeek = startDate.DayOfWeek; System.DayOfWeek endDayOfWeek = dt.DayOfWeek; if((startDayOfWeek == DayOfWeek.Friday)||(startDayOfWeek==DayOfWeek.Saturday)||(startDayOfWeek==DayOfWeek.Sunday)) { dayOfYear = dayOfYear - (7- (int)startDayOfWeek); } else { dayOfYear = dayOfYear + (int)startDayOfWeek; } //dayOfYear+startDayOfWeek <7 则应该为去年的周 if(dayOfYear <0) { DecodeDateWeek(startDate.AddDays(-1),out year,out weekOfYear,out dayOfWeek); } weekOfYear = dayOfYear/7; if( SqlInt32.Mod(dayOfYear,7) != 0) { weekOfYear++; } if(weekOfYear > 52) { endDayOfWeek = startDayOfWeek; if(DateTime.IsLeapYear(dt.Year)) { if((endDayOfWeek == DayOfWeek.Sunday)||(endDayOfWeek == DayOfWeek.Monday)) { endDayOfWeek ++; } if((endDayOfWeek==DayOfWeek.Monday)||(endDayOfWeek==DayOfWeek.Tuesday)||(endDayOfWeek==DayOfWeek.Wednesday)) { year ++; weekOfYear = 1; } } } } private bool IsLastOP(string moCode,string routeCode,string opCode) { if (routeCode==string.Empty) return false; DataCollectFacade dataCollectFacade = new DataCollectFacade(this.DataProvider); return dataCollectFacade.OPIsMORouteLastOP(moCode,routeCode,opCode); } private bool IsMidOutputOP(string itemCode,string routeCode,string opCode,ProductInfo product) { if (routeCode.Trim()==string.Empty) { //BaseModelFacade itemFacade = new BaseModelFacade(this.DataProvider); object obj = null;// itemFacade.GetOperation(opCode); if(obj == null) { /*Burn In 漏扫时,如果到了FT,提示“该产品已经完工或者被替换”这个提示要修改,以便让USER知道是在哪里完工了,并提示要从第一站投入。 建议如果报该提示的时候,即发现该产品已经完工,先不要直接报出来,在后面再加一条检查,检查其完工工序,并报出来。毕竟这种情况不是很多,所以性能方面的顾虑可以排除掉。 * */ if(product.LastSimulation != null && product.LastSimulation.ISCOM == "1") { throw new Exception("$CS_PRODUCT_ALREADY_COMPLETE $CS_Param_OPCode =" + product.LastSimulation.OPCODE); } else { throw new Exception("$CS_Route_Failed_GetNotNextOP"); } } return FormatHelper.StringToBoolean( ((ICSOP)obj).OPCONTROL,(int)OperationList.MidistOutput); } else { //ItemFacade itemFacade = new ItemFacade(this.DataProvider); object obj = null; if(product.CurrentItemRoute2OP != null) { obj = product.CurrentItemRoute2OP; } else { obj = null;// itemFacade.GetItemRoute2Operation(itemCode, routeCode, opCode); } return FormatHelper.StringToBoolean(((ICSITEMROUTE2OP)obj).OPCONTROL, (int)OperationList.MidistOutput); } } //新增 判断是否是中间投入工序 private bool IsMidInputOP(string itemCode,string routeCode,string opCode,ProductInfo product) { //return false; if (routeCode.Trim()==string.Empty) { //BaseModelFacade itemFacade = new BaseModelFacade(this.DataProvider); object obj = null;//itemFacade.GetOperation(opCode); if(obj == null) { /*Burn In 漏扫时,如果到了FT,提示“该产品已经完工或者被替换”这个提示要修改,以便让USER知道是在哪里完工了,并提示要从第一站投入。 建议如果报该提示的时候,即发现该产品已经完工,先不要直接报出来,在后面再加一条检查,检查其完工工序,并报出来。毕竟这种情况不是很多,所以性能方面的顾虑可以排除掉。 * */ if(product.LastSimulation != null && product.LastSimulation.ISCOM == "1") { throw new Exception("$CS_PRODUCT_ALREADY_COMPLETE $CS_Param_OPCode =" + product.LastSimulation.OPCODE); } else { throw new Exception("$CS_Route_Failed_GetNotNextOP"); } } return FormatHelper.StringToBoolean( ((ICSOP)obj).OPCONTROL,(int)OperationList.MidistInput); } else { //ItemFacade itemFacade = new ItemFacade(this.DataProvider); object obj = null; if(product.CurrentItemRoute2OP != null) { obj = product.CurrentItemRoute2OP; } else { obj = null;//itemFacade.GetItemRoute2Operation(itemCode,routeCode,opCode); } return FormatHelper.StringToBoolean( ((ICSITEM2ROUTE)obj).ROUTECODE,(int)OperationList.MidistInput); } } /// /// By Line 统计产量,NG,直通率 /// 处理并发 /// /// /// /// /// public Messages ReportLineQuanMaster(FramDataContext domainDataProvider, string actionType, ProductInfo product) { return ReportLineQuanMaster(domainDataProvider, actionType, product, null); } // 扩展一个带ActionCheckStatus参数的方法 public Messages ReportLineQuanMaster(FramDataContext domainDataProvider, string actionType, ProductInfo product, ActionCheckStatus actionCheckStatus) { Messages messages=new Messages(); ICSReport reportFacade = new ICSReport(domainDataProvider); //TSFacade tSFacade = new TSFacade(domainDataProvider); //MOFacade mOFacade = new MOFacade(domainDataProvider); int ngtimes = 0; int qty = 0; int allqty = 0; int inputQty = 0; int moInputQty = 0; int moAllGoodQty = 0; try { //QtyFlag更改为主键 string flag = String.Empty; bool midOP = false; bool midInputOP = false; if (actionCheckStatus == null || actionCheckStatus.IsMidOutputOP == string.Empty) { if(IsMidOutputOP(product.NowSimulationReport.ITEMCODE,product.NowSimulationReport.ROUTECODE,product.NowSimulationReport.OPCODE,product)) { midOP = true; } if (actionCheckStatus != null) { actionCheckStatus.IsMidOutputOP = midOP.ToString(); } } else { midOP = Convert.ToBoolean(actionCheckStatus.IsMidOutputOP); } if (actionCheckStatus == null || actionCheckStatus.IsMidInputOP == string.Empty) { //中间投入 if(IsMidInputOP(product.NowSimulationReport.ITEMCODE,product.NowSimulationReport.ROUTECODE,product.NowSimulationReport.OPCODE,product)) { midInputOP = true; } if (actionCheckStatus != null) { actionCheckStatus.IsMidInputOP = midInputOP.ToString(); } } else { midInputOP = Convert.ToBoolean(actionCheckStatus.IsMidInputOP); } //是否为最后工序 if (actionCheckStatus == null || actionCheckStatus.IsLastOP == string.Empty) { if (IsLastOP(product.NowSimulationReport.MOCODE,product.NowSimulationReport.ROUTECODE,product.NowSimulationReport.OPCODE))//是否为最后工序 flag = "Y"; else flag = "N"; if (actionCheckStatus != null) { actionCheckStatus.IsLastOP = flag; } } else { flag = actionCheckStatus.IsLastOP; } int iNGStart = 0; int iMoNGStart = 0; #region 更新数量 //在中间投入工序投入的不管是良品还是不良品,皆作为投入量的加项.不存在减项. if(midInputOP) { inputQty = Convert.ToInt32(1 * product.NowSimulation.IDMERGERULE); } if (product.NowSimulation.PRODUCTSTATUS == "GOOD" && product.NowSimulation.LACTION != ActionType.DataCollectAction_GoMO) { if (flag == "Y" || midOP)//是否为最后工序或中间计算工序 { if(product.NowSimulation != null) { //iNGStart = tSFacade.QueryTSCountByLine( // product.NowSimulationReport.RCARD // ,product.NowSimulationReport.SSCODE // ,Convert.ToInt32(product.NowSimulationReport.RCARDSEQ)); //iMoNGStart = tSFacade.QueryTSCountByMo( // product.NowSimulation.RCARD // ,product.NowSimulation.MOCODE); } qty = Convert.ToInt32(1 * product.NowSimulation.IDMERGERULE); //直通产量不准 //if ( // iNGStart == 0 && IDIsInRejectCount(product.NowSimulationReport.RCARD,product.NowSimulationReport.SSCODE)==0) //{ // //reportRealtimeLineQty.AllGoodQty += 1 * product.NowSimulation.IDMERGERULE; // allqty = Convert.ToInt32(1 * product.NowSimulation.IDMERGERULE); //} //工单直通台数 #region 有关产量、投入数、不良率、直通率的补充说明: /*3. 工单直通率: =(工单(正常工单或返工工单)从投入到产出的过程中未曾出现过不良的产品台数)/该工单(正常工单或返工工单)中完成的产品良品台数 对产线判断直通产品数量时,一定要分工单。如果产线做的是A工单,只需判断该产品序列号在A工单(注意是工单,而不是产线+工单。 对于中间产线,可能该产品序列号在其上未发现不良,但在前面的产线如果出现不良,仍是该中间产线的非直通品)的生产过程中是否出现了不良,如有不良则为非直通品。即使该产品序列号在其他工单中曾出现过不良,但对该次的生产不影响到直通台数的计算。 直通率不存在跨时段的问题.只要发现其在工单中曾出现过不良,则不会记录为直通品。没有不良就记录为直通品,然后归属到时段。 该工单回流的产品一定不是直通品 FQC抽检为不良或被判退的产品一定不是直通品 */ #endregion //if (flag == "Y" && iMoNGStart == 0 // && IDIsInRejectCountByMo(product.NowSimulationReport.RCARD,product.NowSimulationReport.MOCODE)==0 // && product.NowSimulationReport.NGTIMES == 0) //{ // moAllGoodQty = Convert.ToInt32(1 * product.NowSimulation.IDMERGERULE); //} } } else if (product.NowSimulation.PRODUCTSTATUS == "NG") { //reportRealtimeLineQty.NGTimes += 1; //投入量的计算 //如果出现TS,并且产品前一次状态和现在的NG状态不等 //并且前一次Action和现在的Action是在同一道工序 //采集NG,投入数应该减少 //避免直接采集NG,减投入数的bug //Eric 在中间投入工序投入的不管是良品还是不良品,皆作为投入量的加项.不存在减项. ngtimes = 1; if (product.NowSimulation.OPCODE == product.LastSimulation.OPCODE && (product.LastSimulation.LACTION == ActionType.DataCollectAction_GOOD || product.LastSimulation.LACTION == ActionType.DataCollectAction_SMTGOOD || product.LastSimulation.LACTION == ActionType.DataCollectAction_OutLineGood || product.LastSimulation.LACTION == ActionType.DataCollectAction_OQCPass) ) { if (flag == "Y" || midOP)//是否为最后工序或中间计算工序 { //当前站有过操作,并且前一次操作状态是GOOD才会减数量 qty = Convert.ToInt32(-1 * product.NowSimulation.IDMERGERULE); if(product.NowSimulation != null) { //iNGStart = tSFacade.QueryTSCountByLine( // product.NowSimulationReport.RCARD // ,product.NowSimulationReport.SSCODE // ,Convert.ToInt32(product.NowSimulationReport.RCARDSEQ)); //iMoNGStart = tSFacade.QueryTSCountByMo( // product.NowSimulation.RCARD // ,product.NowSimulation.MOCODE); } //直通产量不准 //if ((IDIsInRejectCount(product.NowSimulationReport.RCARD,product.NowSimulationReport.SSCODE)==0) // && iNGStart == 0)//rejectlist //{ // allqty = Convert.ToInt32(-1 * product.NowSimulation.IDMERGERULE); //} //工单直通台数 #region 有关产量、投入数、不良率、直通率的补充说明: /*3. 工单直通率: =(工单(正常工单或返工工单)从投入到产出的过程中未曾出现过不良的产品台数)/该工单(正常工单或返工工单)中完成的产品良品台数 对产线判断直通产品数量时,一定要分工单。如果产线做的是A工单,只需判断该产品序列号在A工单(注意是工单,而不是产线+工单。 对于中间产线,可能该产品序列号在其上未发现不良,但在前面的产线如果出现不良,仍是该中间产线的非直通品)的生产过程中是否出现了不良,如有不良则为非直通品。即使该产品序列号在其他工单中曾出现过不良,但对该次的生产不影响到直通台数的计算。 直通率不存在跨时段的问题.只要发现其在工单中曾出现过不良,则不会记录为直通品。没有不良就记录为直通品,然后归属到时段。 该工单回流的产品一定不是直通品 FQC抽检为不良或被判退的产品一定不是直通品 */ #endregion //if (flag == "Y" && iMoNGStart == 0 // && IDIsInRejectCountByMo(product.NowSimulationReport.RCARD, product.NowSimulationReport.MOCODE) == 0 // && product.NowSimulationReport.NGTIMES == 1) //{ // moAllGoodQty = Convert.ToInt32(-1 * product.NowSimulation.IDMERGERULE); //} } } } else if (product.NowSimulation.PRODUCTSTATUS == "REJECT") { if (product.NowSimulation.RESCODE == product.LastSimulation.RESCODE && (product.LastSimulation.LACTION == ActionType.DataCollectAction_GOOD || product.LastSimulation.LACTION == ActionType.DataCollectAction_SMTGOOD || product.LastSimulation.LACTION == ActionType.DataCollectAction_OutLineGood || product.LastSimulation.LACTION == ActionType.DataCollectAction_OQCPass) ) { if (flag == "Y" || midOP)//是否为最后工序或中间计算工序 { //reportRealtimeLineQty.OuputQty -= 1 * product.NowSimulation.IDMERGERULE; if(product.NowSimulationReport != null) { //iNGStart = tSFacade.QueryTSCountByLine( // product.NowSimulationReport.RCARD // ,product.NowSimulationReport.SSCODE // ,Convert.ToInt32(product.NowSimulationReport.RCARDSEQ)); //iMoNGStart = tSFacade.QueryTSCountByMo( // product.NowSimulation.RCARD // ,product.NowSimulation.MOCODE); } //直通产量不准 qty = Convert.ToInt32(-1 * product.NowSimulation.IDMERGERULE); //if ((IDIsInRejectCount(product.NowSimulationReport.RCARD,product.NowSimulationReport.SSCODE)==1) // && iNGStart == 0) //{ // allqty = Convert.ToInt32( -1 * product.NowSimulation.IDMERGERULE); //} //工单直通台数 #region 有关产量、投入数、不良率、直通率的补充说明: ///3. 工单直通率: ///=(工单(正常工单或返工工单)从投入到产出的过程中未曾出现过不良的产品台数)/该工单(正常工单或返工工单)中完成的产品良品台数 ///对产线判断直通产品数量时,一定要分工单。如果产线做的是A工单,只需判断该产品序列号在A工单(注意是工单,而不是产线+工单。 对于中间产线,可能该产品序列号在其上未发现不良,但在前面的产线如果出现不良,仍是该中间产线的非直通品)的生产过程中是否出现了不良,如有不良则为非直通品。即使该产品序列号在其他工单中曾出现过不良,但对该次的生产不影响到直通台数的计算。 ///直通率不存在跨时段的问题.只要发现其在工单中曾出现过不良,则不会记录为直通品。没有不良就记录为直通品,然后归属到时段。 ///该工单回流的产品一定不是直通品 ///FQC抽检为不良或被判退的产品一定不是直通品 /// #endregion //if (flag == "Y" && iMoNGStart == 0 // && IDIsInRejectCountByMo(product.NowSimulationReport.RCARD, product.NowSimulationReport.MOCODE) == 0 // && product.NowSimulationReport.NGTIMES == 1) //{ // moAllGoodQty = Convert.ToInt32(-1 * product.NowSimulation.IDMERGERULE); //} } } } #endregion if(product.NowSimulationReport.LACTION == ActionType.DataCollectAction_GoMO) { moInputQty = Convert.ToInt32(1 * product.NowSimulation.IDMERGERULE); } //处理并发问题 //没有数字、不是脱离工单什么都不做,节省系统资源 if(ngtimes != 0 || qty != 0 || allqty != 0 || inputQty != 0 || moInputQty != 0 || moAllGoodQty != 0 || actionType == ActionType.DataCollectAction_OffMo/*脱离工单允许*/) { //没有数字什么都不做,节省系统资源 if(ngtimes != 0 || qty != 0 || allqty != 0 || inputQty != 0 || moInputQty != 0 || moAllGoodQty != 0) { #region 获取报表实体 #endregion } } if(product.NowSimulationReport.LACTION == ActionType.DataCollectAction_OffMo || product.NowSimulationReport.LACTION == ActionType.DataCollectAction_GoMO || flag == "Y") { //允许更新工单的脱离数量 //mOFacade.UpdateMOQty(product.NowSimulationReport.MOCODE // ,product.NowSimulationReport.LACTION // ,Convert.ToInt32(1 * product.NowSimulation.IDMERGERULE)); } } catch (Exception e) { messages.Add(new Message(e)); } return messages; } //应该是没有考虑到回流和重工的情况 //检查是否在当前站已经做过统计 private bool CheckNeedCountInthisResoure(ProductInfo product) { if (product.NowSimulation.RESCODE == product.LastSimulation.RESCODE && product.NowSimulation.OPCODE == product.LastSimulation.OPCODE && ( product.LastSimulation.LACTION == ActionType.DataCollectAction_GOOD || product.LastSimulation.LACTION == ActionType.DataCollectAction_SMTGOOD || product.LastSimulation.LACTION == ActionType.DataCollectAction_OutLineGood || product.LastSimulation.LACTION == ActionType.DataCollectAction_CollectKeyParts || product.LastSimulation.LACTION == ActionType.DataCollectAction_CollectINNO || product.LastSimulation.LACTION == ActionType.DataCollectAction_IDTran || product.LastSimulation.LACTION == ActionType.DataCollectAction_Split ) ) return true; else return false; } } /// /// 周的计算 /// /// [Serializable] public class WeekObject { public int Week; } /// /// /// /// [Serializable] public struct ReportQtyHelper { public decimal OuputQty; public decimal AllGoodQty; public decimal MoAllGoodQty; public ReportQtyHelper( decimal ouputQty, decimal allGoodQty, decimal moAllGoodQty) { OuputQty = ouputQty ; AllGoodQty = allGoodQty ; MoAllGoodQty= moAllGoodQty ; } } }