private ErrorMessageDTO CalculateAction(CalculateOperatorBonus bpObj) { ErrorMessageDTO errorDot = new ErrorMessageDTO(); // 1、 bpObj.Type 为0计算采购业务员奖金,为1计算包装业务员奖金; //2、bpObj.OperatorsList为空或者bpObj.OperatorsList.Count为0计算指定会计期间内的所有业务员,反之计算指定业务员奖金 //操作事件区分,0计算,1补算,2取消计算 if (bpObj.CalculateType == 0) { #region 计算奖金功能 //计算奖金 #region 计算前校验 //1、所选会计期间状态必须为“未计算”, foreach (BonusCalculateRecordBE.BonusCalculateRecordDTO dto in bpObj.BonusCalcuteList) { //勾选的会计期间必须是当前月度前的会计期间并且期间状态是“未计算”的; if (dto.PeriodStatus == EnumBE.PeriodStatusEnum.Calculate || dto.PeriodStatus == EnumBE.PeriodStatusEnum.RepairCalculate) { throw new Exception("会计期间" + dto.SOBAccountingPeriod.DisplayName + "已计算奖金"); } if (dto.SOBAccountingPeriod != null && dto.SOBAccountingPeriod.DisplayName != "") { if (Convert.ToDateTime(dto.SOBAccountingPeriod.DisplayName) >= Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM"))) { throw new Exception("会计期间" + dto.SOBAccountingPeriod.DisplayName + "必须是当前月度前的会计期间"); } } } //2、勾选的会计期间前一个会计期间必须已完成计算, //找到最小的会计期间,判断它的前一个会计期间是否已计算 var minPeriodNumber = bpObj.BonusCalcuteList.Min <BonusCalculateRecordDTO>(p => p.SOBAccountingPeriod.Number); if ((Convert.ToInt32(minPeriodNumber) - 10) > 0) //前一个会计期间不为XXXX-01(即本年度第一个会计期间) { //勾选的最小会计期间前一个会计期间必须已完成计算, BonusCalculateRecordBE.BonusCalculateRecord record = BonusCalculateRecordBE.BonusCalculateRecord.Finder.Find("SourceType=" + bpObj.Type + " and SOBAccountingPeriod.Year=" + bpObj.Year + " and SOBAccountingPeriod.Number=" + (Convert.ToInt32(minPeriodNumber) - 10) + ""); //BonusCalculateRecordBE.BonusCalculateRecord.EntityList recoudList = BonusCalculateRecordBE.BonusCalculateRecord.Finder.FindAll("1=1"); if (record == null || record.PeriodStatus == EnumBE.PeriodStatusEnum.NoCalculate) { throw new Exception("勾选的最小会计期间前一个会计期间必须已完成计算"); } } //3、如果勾选多个,则必须是连续性的会计期间,中间不允许出现未计算的或者没有勾选的; //先排序,再判断是否连续会计期间 IEnumerable <BonusCalculateRecordDTO> recordDTO = from calDTO in bpObj.BonusCalcuteList orderby calDTO.SOBAccountingPeriod.Number descending select calDTO; int number = 0;//判断是否连续的标志 foreach (BonusCalculateRecordDTO bonusDTO in recordDTO) { if (number != 0) { if (number != bonusDTO.SOBAccountingPeriod.Number) { throw new Exception("请勾选连续的会计期间进行计算"); } } number = bonusDTO.SOBAccountingPeriod.Number; } #endregion 校验结束 #region 校验通过,计算奖金 //奖金计算时,不区分组织,即统计发生在勾选的会计期间范围内的已审核的付款通知单, //并且付款通知单来源采购订单的业务员类型为产品采购的(组织间的抛单业务除外), //根据业务员进行分组,计算业务员奖金, #region 获取预置参数 decimal bonusCoefficient = 0; //奖金系数 decimal degradationCoefficient = 0; //降价系数 decimal packaingBonusCoefficient = 0; //包装奖金系数 int deliveryExpectDay = 0; //交货基准交期 GetSysteParma(bonusCoefficient, degradationCoefficient, packaingBonusCoefficient, deliveryExpectDay); //获取预置参数值 #endregion #region 查询付款通知单 //获得会计期间的最大、最小时间 if (recordDTO == null || recordDTO.Count <BonusCalculateRecordDTO>() == 0) { throw new Exception("请选择计算的会计期间"); } //会计期间的最小时间 string startTime = DateTime.Parse(recordDTO.First <BonusCalculateRecordDTO>().SOBAccountingPeriod.DisplayName).ToString("yyyy-MM-01 00:00:00"); //string endTime = DateTime.Parse(recordDTO.Last<BonusCalculateRecordDTO>().SOBAccountingPeriod.DisplayName).ToString("yyyy-MM- //会计期间的最大时间 int year = DateTime.Parse(recordDTO.Last <BonusCalculateRecordDTO>().SOBAccountingPeriod.DisplayName).Year; int month = DateTime.Parse(recordDTO.Last <BonusCalculateRecordDTO>().SOBAccountingPeriod.DisplayName).Month; int days = DateTime.DaysInMonth(year, month); DateTime datetime = new DateTime(year, month, 1); string endTime = datetime.AddDays(days - 1).ToString("yyyy-MM-dd 23:59:59"); //获取付款通知单数据集 DataTable tablePayment = GetPaymentData(bpObj, DateTime.Parse(startTime), DateTime.Parse(endTime)); #endregion string docNo = ""; #region 生成业务员奖金 if (bpObj.Type == 0)//生成采购业务员奖金 { docNo = CreateProductOperatorBonus(bpObj, tablePayment, bonusCoefficient, degradationCoefficient, deliveryExpectDay); } else //生成包装业务员奖金 { docNo = CreatePackagingOperatorBonus(bpObj, tablePayment, packaingBonusCoefficient); } #endregion #region 生成奖金计算记录 using (ISession session = Session.Open()) { BonusCalculateRecord bonusRecord = null; foreach (BonusCalculateRecordDTO bonusDTO in bpObj.BonusCalcuteList) { bonusRecord = BonusCalculateRecord.Create(); if (bpObj.Type == 0) { bonusRecord.SourceType = EnumBE.BonusOperatorsTypeEnum.ProductOperators; } else { bonusRecord.SourceType = EnumBE.BonusOperatorsTypeEnum.PackagingOperators; } bonusRecord.SOBAccountingPeriodKey = bonusDTO.SOBAccountingPeriod.Key; bonusRecord.Oprator = UFIDA.U9.Base.Context.LoginUser; bonusRecord.OprateTime = DateTime.Now; bonusRecord.PeriodStatus = EnumBE.PeriodStatusEnum.Calculate; bonusRecord.Org = UFIDA.U9.Base.Context.LoginOrg; bonusRecord.OperatorBonus = docNo; } session.Commit(); } #endregion if (docNo != "") { //生成成功,发送消息 List <long> recever = new System.Collections.Generic.List <long>(); recever.Add(Convert.ToInt64(UFIDA.U9.Base.Context.LoginUserID)); UFIDA.U9.Cust.GS.FI.FIBP.PubBP.SendMessageExtend.SendMessage("计算业务员奖金完成,生成单号" + docNo, "业务员奖金计算完成通知", recever, UFIDA.U9.BS.Notification.PriorityEnum.Medium); } #endregion #endregion 计算End } else if (bpObj.CalculateType == 1) { #region 补算 #region 补算前校验 //可以通过计算范围选择性的选择业务员进行奖金的补算,补算可以跨月进行,补算完后,记录补算的结果,并产生差异明细; foreach (BonusCalculateRecordBE.BonusCalculateRecordDTO dto in bpObj.BonusCalcuteList) { //勾选的会计期间必须是当前月度前的会计期间并且期间状态是“未计算”的; if (dto.PeriodStatus == EnumBE.PeriodStatusEnum.NoCalculate) { throw new Exception("会计期间" + dto.SOBAccountingPeriod.DisplayName + "未计算奖金,不能补算"); } } #endregion 补算前校验End #region 获取预置参数 decimal bonusCoefficient = 0; //奖金系数 decimal degradationCoefficient = 0; //降价系数 decimal packaingBonusCoefficient = 0; //包装奖金系数 int deliveryExpectDay = 0; //交货基准交期 GetSysteParma(bonusCoefficient, degradationCoefficient, packaingBonusCoefficient, deliveryExpectDay); //获取预置参数值 #endregion #region 补算 //获取付款通知单数据集,因为可以跨月计算,所以根据每个会计期间查询 DataTable tablePayment = GetPaymentData(bpObj, DateTime.Now, DateTime.Now); string docNo = ""; #region 生成业务员奖金 if (bpObj.Type == 0)//生成采购业务员奖金 { docNo = CreateProductOperatorBonus(bpObj, tablePayment, bonusCoefficient, degradationCoefficient, deliveryExpectDay); } else //生成包装业务员奖金 { docNo = CreatePackagingOperatorBonus(bpObj, tablePayment, packaingBonusCoefficient); } #endregion #region 生成奖金计算记录 using (ISession session = Session.Open()) { BonusCalculateRecord bonusRecord = null; foreach (BonusCalculateRecordDTO bonusDTO in bpObj.BonusCalcuteList) { bonusRecord = BonusCalculateRecord.Create(); if (bpObj.Type == 0) { bonusRecord.SourceType = EnumBE.BonusOperatorsTypeEnum.ProductOperators; } else { bonusRecord.SourceType = EnumBE.BonusOperatorsTypeEnum.PackagingOperators; } bonusRecord.SOBAccountingPeriodKey = bonusDTO.SOBAccountingPeriod.Key; bonusRecord.Oprator = UFIDA.U9.Base.Context.LoginUser; bonusRecord.OprateTime = DateTime.Now; bonusRecord.PeriodStatus = EnumBE.PeriodStatusEnum.RepairCalculate;//补算 bonusRecord.Org = UFIDA.U9.Base.Context.LoginOrg; bonusRecord.RepairOperatorBonus = docNo; } session.Commit(); } #endregion if (docNo != "") { //生成成功,发送消息 List <long> recever = new System.Collections.Generic.List <long>(); recever.Add(Convert.ToInt64(UFIDA.U9.Base.Context.LoginUserID)); UFIDA.U9.Cust.GS.FI.FIBP.PubBP.SendMessageExtend.SendMessage("计算业务员奖金完成,生成单号" + docNo, "业务员奖金计算完成通知", recever, UFIDA.U9.BS.Notification.PriorityEnum.Medium); } #endregion 补算 End #endregion 补算 } else if (bpObj.CalculateType == 2) { #region 取消计算 //1、勾选的会计期间前后的会计期间状态必须是“未计算”的,否则提示不允许取消; //2、校验通过后,删除勾选的会计期间对应的业务员奖金计算结果 #region 取消计算前校验 foreach (BonusCalculateRecordBE.BonusCalculateRecordDTO dto in bpObj.BonusCalcuteList) { //勾选的会计期间必须是当前月度前的会计期间并且期间状态是“未计算”的; if (dto.PeriodStatus == EnumBE.PeriodStatusEnum.NoCalculate) { throw new Exception("会计期间" + dto.SOBAccountingPeriod.DisplayName + "未计算奖金,无需取消计算"); } } #endregion 取消计算前校验 end #region 取消计算 using (ISession session = Session.Open()) { BonusProductDoc bonusProduct = null; BonusPackagingDoc bonusPackaging = null; foreach (BonusCalculateRecordBE.BonusCalculateRecordDTO dto in bpObj.BonusCalcuteList) { if (dto.ID > 0) { if (bpObj.Type == 0)//采购业务员奖金 { bonusProduct = BonusProductDoc.Finder.Find("OperatorBonus='" + dto.OperatorBonus + "'"); if (bonusProduct != null) { bonusProduct.Remove(); } } else if (bpObj.Type == 1)//包装业务员奖金 { bonusPackaging = BonusPackagingDoc.Finder.Find("OperatorBonus='" + dto.OperatorBonus + "'"); if (bonusPackaging != null) { bonusPackaging.Remove(); } } } } session.Commit(); } #endregion #endregion } return(errorDot); }
/// <summary> /// 创建采购业务员奖金 /// </summary> /// <param name="bpObj">BP入口参数:会计期间集合</param> /// <param name="dsPayment">付款通知单数据集</param> /// <param name="bonusCoefficient">奖金系数</param> /// <param name="degradationCoefficient">降价系数</param> /// <param name="DeliveryExpectDay">基准交期</param> private string CreateProductOperatorBonus(CalculateOperatorBonus bpObj, DataTable dsPayment, decimal bonusCoefficient, decimal degradationCoefficient, int DeliveryExpectDay) { if (dsPayment == null || dsPayment.Rows.Count == 0) { return(""); } var groupOperators = dsPayment.Rows.Cast <DataRow>().GroupBy(t => t["Operators_Code"].ToString()); BonusOperatorDocType bonusType = BonusOperatorDocType.Finder.Find("BuzType=0 and IsCreatedByPush=1"); if (bonusType == null) { throw new Exception("请设置产品采购业务员单据类型并设置为上游单据推出"); } using (ISession session = Session.Open()) { BonusProductDoc bonusProduct = BonusProductDoc.Create(); bonusProduct.DocumentTypeKey = bonusType.Key; //单据类型 bonusProduct.BusinessDate = DateTime.Now; //业务日期 bonusProduct.Status = EnumBE.FICommonStatusEnum.Opened; if (bpObj.BonusCalcuteList[0].SOBAccountingPeriod != null && bpObj.BonusCalcuteList[0].SOBAccountingPeriod.AccountPeriod != null) { bonusProduct.AccountPeriodKey = bpObj.BonusCalcuteList[0].SOBAccountingPeriod.AccountPeriod.AccountingCalendarKey; //会计日历 } bonusProduct.CurrencyKey = Base.Currency.Currency.Finder.Find("Code='C001'").Key; //币种只会为人民币,写死 bonusProduct.Oprator = Base.Context.LoginUser; bonusProduct.OprateDate = DateTime.Now; //设置默认行号 GetProfileValueProxy lineNo = new GetProfileValueProxy(); lineNo.ProfileCode = "SysLineNo"; PVDTOData pVTDOData = lineNo.Do(); string row = pVTDOData.ProfileValue; //根据业务员分组后的付款通知单数据 foreach (var groupOperator in groupOperators) { decimal sumPayment = 0; //付款单总额, decimal sumPerformance = 0; //业绩单总额 decimal productBonusTotal = 0; //新产品奖金合计 decimal depreciateBonusTotal = 0; //降价奖金合计 decimal bonusTotal = 0; //奖金合计 long operatorsKey = Convert.ToInt64(groupOperator.First <DataRow>()["Operators"].ToString()); long dept = Convert.ToInt64(groupOperator.First <DataRow>()["Department"].ToString()); BonusProductDocLine productLine = BonusProductDocLine.Create(bonusProduct); //业务员奖金明细行 productLine.DocLineNo = Convert.ToInt32(row); //行号 if (operatorsKey > 0) { productLine.OperatorsKey = CBO.HR.Operator.Operators.Finder.FindByID(operatorsKey).Key;//业务员 } if (dept > 0) { productLine.DepartmentKey = CBO.HR.Department.Department.Finder.FindByID(dept).Key;//部门 } //设置默认行号 string subRow = pVTDOData.ProfileValue; foreach (DataRow Operator in groupOperator) { if (Convert.ToInt32(Operator["SrcDocType"].ToString()) != EnumBE.PaySrcDocTypeEnum.Rcv.Value) { continue; } BonusProductDocSubLine subLine = BonusProductDocSubLine.Create(productLine); subLine.DocLineNo = Convert.ToInt32(subRow); subLine.OperatorsKey = CBO.HR.Operator.Operators.Finder.FindByID(operatorsKey).Key; //业务员 subLine.DepartmentKey = CBO.HR.Department.Department.Finder.FindByID(dept).Key; //部门 decimal payment = decimal.Parse(Operator["Payment"].ToString()); //付款单金额,转换成人民币 subLine.Payment = payment; sumPayment += payment; //获得产品系数档案 ProductCoefficient coefficient = ProductCoefficient.Finder.Find("ItemMaster.Code='" + Operator["Item_Code"].ToString() + "'"); if (coefficient == null) { throw new Exception("料品" + Operator["Item_Code"].ToString() + " " + Operator["Item_Name"].ToString() + "没有维护产品系数"); } subLine.ProductCoefficient = coefficient; //产品系数 subLine.NewProductCoefficient = coefficient; //新产品系数 //来源类型入库单取实际入库时间 if (Convert.ToInt32(Operator["Item_Code"].ToString()) == 3) { if (Operator["Item_Code"].ToString() != "") { long rcvId = Convert.ToInt64(Operator["Item_Code"].ToString()); if (rcvId > 0) { PM.Rcv.RcvLine rcvLine = PM.Rcv.RcvLine.Finder.FindByID(rcvId); if (rcvLine != null) { subLine.PracticalRcvTime = rcvLine.ConfirmDate;//实际入库时间 } else { throw new Exception("付款通知单" + Operator["Payment_DocNo"].ToString() + "行" + Operator["SrcDocLineNo"].ToString() + "找不到来源入库单"); } } } } //应交货日期取收购单上的应交货日期。 //PM.PO.POShipLine shipLine = PM.PO.POShipLine.Finder.FindByID(Operator["POShipLineID"].ToString()); //if (shipLine != null) //{ // subLine.DeliveryTime = shipLine.DeliveryDate;//应交货日期 //} if (Operator["SPDelivery"].ToString() != "") { subLine.DeliveryTime = DateTime.Parse(Operator["SPDelivery"].ToString()); } subLine.DegradationCoefficient = degradationCoefficient; //降价系数,预置参数 //计算交付预期与计算奖金相关 //1、如果来源采购 #region 计算交付预期和奖金,默认1 decimal deliveryExpect = 1; //库存采购不考虑逾期,用采购单据类型编号判断; //判断如果逾期,则置为-1 if (Operator["DocumentType"].ToString() != "PO03") ///库存采购单据类型编码目前默认PO03,后期基础数据准备完成后相应改动 { //在奖金计算时,如果该批号对应的数量大于在预留表里面的对应批号的数量,说明多余的数量已转自由库存, //需同时计算不考虑逾期的奖金和预留数量对应的受预期影响的奖金两部分 if (Operator["Lot"].ToString() != "") { long lot = Convert.ToInt64(Operator["Lot"].ToString()); //获取预留表批号 UFIDA.U9.ATP.Reserve.Reserve reserve = ATP.Reserve.Reserve.Finder.Find("SupplyLot=" + lot + ""); if (reserve != null && reserve.ReserveQtyIU < decimal.Parse(Operator["PayQty"].ToString())) { //比预留表多余的数量表示已经转自由库存,不考虑预期,计算奖金 subLine.Bonus = decimal.Parse(Operator["FinallyPrice"].ToString()) * (decimal.Parse(Operator["PayQty"].ToString()) - reserve.ReserveQtyIU) * bonusCoefficient * coefficient.Coefficien * coefficient.ProductCoeffien * deliveryExpect; //实际入库时间-收购单(供应计划)下单日>基准交期,并且大于交货日期,则逾期系数为-1,负奖金,需要扣奖金; if (subLine.DeliveryTime != null && (subLine.PracticalRcvTime - Convert.ToDateTime(Operator["CreatedOn"].ToString())).Days > DeliveryExpectDay && subLine.PracticalRcvTime > subLine.DeliveryTime)//逾期,扣奖金 { deliveryExpect = -1; subLine.DeliveryExpect = deliveryExpect; //计算奖金 subLine.Bonus += decimal.Parse(Operator["FinallyPrice"].ToString()) * reserve.ReserveQtyIU * bonusCoefficient * coefficient.Coefficien * coefficient.ProductCoeffien * deliveryExpect; } else { deliveryExpect = 1; subLine.DeliveryExpect = deliveryExpect; //计算奖金 subLine.Bonus += decimal.Parse(Operator["FinallyPrice"].ToString()) * reserve.ReserveQtyIU * bonusCoefficient * coefficient.Coefficien * coefficient.ProductCoeffien * deliveryExpect; } } else { //throw new Exception("付款通知单" + Operator["Payment_DocNo"].ToString() + "行" + Operator["SrcDocLineNo"].ToString() + "入库批号找不到预留表对应批号"); //实际入库时间-收购单(供应计划)下单日>基准交期,并且大于交货日期,则逾期系数为-1,负奖金,需要扣奖金; if (subLine.DeliveryTime != null && (subLine.PracticalRcvTime - Convert.ToDateTime(Operator["CreatedOn"].ToString())).Days > DeliveryExpectDay && subLine.PracticalRcvTime > subLine.DeliveryTime)//逾期,扣奖金 { deliveryExpect = -1; subLine.DeliveryExpect = deliveryExpect; //计算奖金 subLine.Bonus = payment * bonusCoefficient * coefficient.Coefficien * coefficient.ProductCoeffien * deliveryExpect; } else { deliveryExpect = 1; subLine.DeliveryExpect = deliveryExpect; //计算奖金 subLine.Bonus = payment * bonusCoefficient * coefficient.Coefficien * coefficient.ProductCoeffien * deliveryExpect; } } } else //找不到对应批号,直接判断是否逾期,正常流程基本不存在的 { //实际入库时间-收购单(供应计划)下单日>基准交期,并且大于交货日期,则逾期系数为-1,负奖金,需要扣奖金; if (subLine.DeliveryTime != null && (subLine.PracticalRcvTime - Convert.ToDateTime(Operator["CreatedOn"].ToString())).Days > DeliveryExpectDay && subLine.PracticalRcvTime > subLine.DeliveryTime)//逾期,扣奖金 { deliveryExpect = -1; subLine.DeliveryExpect = deliveryExpect; //计算奖金 subLine.Bonus = payment * bonusCoefficient * coefficient.Coefficien * coefficient.ProductCoeffien * deliveryExpect; } else { deliveryExpect = 1; subLine.DeliveryExpect = deliveryExpect; //计算奖金 subLine.Bonus = payment * bonusCoefficient * coefficient.Coefficien * coefficient.ProductCoeffien * deliveryExpect; } } } else //库存采购 { //库存采购不考虑逾期 deliveryExpect = 1; subLine.DeliveryExpect = deliveryExpect; //计算奖金 subLine.Bonus = payment * bonusCoefficient * coefficient.Coefficien * coefficient.ProductCoeffien * deliveryExpect; } #endregion subLine.PaymentDocKey = PaymentBE.Payment.Finder.FindByID(Operator["PaymentID"].ToString()).Key; subLine.PaymentDocNo = Operator["Payment_DocNo"].ToString(); subLine.ItemKey = CBO.SCM.Item.ItemMaster.Finder.FindByID(Operator["Item"].ToString()).Key; subLine.SrcDocLineNo = Convert.ToInt32(Operator["SrcDocLineNo"].ToString()); //降价奖金 ProductDepreciate productDepreciate = ProductDepreciate.Finder.Find("ItemMaster.Code='" + Operator["Item_Code"].ToString() + "'"); if (productDepreciate != null) { depreciateBonusTotal += productDepreciate.CanPrice * Decimal.Parse(Operator["PayQty"].ToString()) * degradationCoefficient; } subRow = (int.Parse(subRow) + int.Parse(pVTDOData.ProfileValue)).ToString();//自增行号 } productLine.SumPayment = sumPayment; productLine.SumPerformance = sumPerformance; productLine.ProductBonusTotal = productBonusTotal; productLine.DepreciateBonusTotal = depreciateBonusTotal; productLine.BonusTotal = bonusTotal; row = (int.Parse(row) + int.Parse(pVTDOData.ProfileValue)).ToString();//自增行号 } session.Commit(); return(bonusProduct.DocNo); } }