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 ;
}
}
}