diff --git a/CY.SAL_OUTSTOCK/AutoPushLostOutStock2Pay.cs b/CY.SAL_OUTSTOCK/AutoPushLostOutStock2Pay.cs index de05fc4..3d03bf6 100644 --- a/CY.SAL_OUTSTOCK/AutoPushLostOutStock2Pay.cs +++ b/CY.SAL_OUTSTOCK/AutoPushLostOutStock2Pay.cs @@ -18,6 +18,9 @@ using Kingdee.BOS.Orm.DataEntity; using Kingdee.BOS.Core.BusinessFlow.ServiceArgs; using Kingdee.BOS.Core.Metadata; using Kingdee.BOS.App.Core.ScheduleService; +using Kingdee.BOS.App; +using Kingdee.BOS.Core.DynamicForm; +using Kingdee.BOS.Log; namespace CY.SAL_OUTSTOCK { @@ -26,62 +29,79 @@ namespace CY.SAL_OUTSTOCK { public void Run(Context ctx, Schedule schedule) { - + Logger.Info(schedule.Name, $"销售出库单自动下推应付单start..."); + var succeedNum = 0; + var failNum = 0; try { - IConvertService service = Kingdee.BOS.App.ServiceHelper.GetService(); + IConvertService service = ServiceHelper.GetService(); + //源单据标识 string sourceFormId = "SAL_OUTSTOCK"; - + //目标单据标识 string targetFormId = "AR_RECEIVABLE"; - - //var rules = service.GetConvertRules(ctx, sourceFormId, targetFormId); - + //目标单据类型id-标准应收单 + string targetBillTypeId = "180ecd4afd5d44b5be78a6efe4a7e041"; + //转换规则 string convertRuleId = "AR_OutStockToReceivableMap"; //销售出库单下推应付单 - var ruleMeta = service.GetConvertRule(ctx, convertRuleId); var rule = ruleMeta.Rule; var dbList = GetDBData(ctx); if (dbList != null && dbList.Any()) { - var groupbyList = dbList.GroupBy(x => x["FBILLNO"]); - StringBuilder stringBuilder = new StringBuilder(); + var groupbyList = dbList.GroupBy(x => x["FBILLNO"].ToString()); + Logger.Info(schedule.Name, $"找到{groupbyList.Count()}条数据"); + foreach (var list in groupbyList) { + List selectedRows = list.Select(x => new ListSelectedRow(x["FID"].ToString(), x["FENTRYID"].ToString(), 0, sourceFormId)).ToList(); + + PushArgs pushArgs = new PushArgs(rule, selectedRows.ToArray());//下推入口参数 + pushArgs.TargetBillTypeId = targetBillTypeId; + + OperateOption option = OperateOption.Create();//选项参数 + try { - List selectedRows = list.Select(x => new ListSelectedRow(x["FID"].ToString(), x["FENTRYID"].ToString(), 0, sourceFormId)).ToList(); + ConvertOperationResult convertResult = service.Push(ctx, pushArgs, option); - PushArgs pushArgs = new PushArgs(rule, selectedRows.ToArray());//下推入口参数 + DynamicObject[] destObjs = convertResult.TargetDataEntities.Select(r => r.DataEntity).ToArray(); - OperateOption option = OperateOption.Create();//选项参数 + FormMetadata destFormMetadata = ServiceHelper.GetService().Load(ctx, targetFormId) as FormMetadata; - ConvertOperationResult result = service.Push(ctx, pushArgs, option); + IOperationResult saveResult = ServiceHelper.GetService().Save(ctx, destFormMetadata.BusinessInfo, destObjs, OperateOption.Create()); + + if (saveResult.ValidationErrors != null && saveResult.ValidationErrors.Count > 0) + { + var errorInfo = string.Join(";", saveResult.ValidationErrors.Select(x => x.Message)); + + throw new KDBusinessException("", "未知原因导致自动保存失败原因:" + errorInfo); + } + else + { + succeedNum++; + Logger.Info(schedule.Name, $"销售出库单:{list.Key}下推应付单:{saveResult.OperateResult[0].Number}成功!"); + } } - catch (Exception ex) + catch (KDBusinessException ex) { - stringBuilder.AppendLine($"单据:{list.Key}下推失败"); + failNum++; + Logger.Error($"服务器插件:{schedule.Name}", $"销售出库单:{list.Key}", ex); } } - if (stringBuilder.IsNullOrEmpty()) - throw new Exception(stringBuilder.ToString()); } } catch (Exception ex) { - ScheduleMsgDal _msgDal = new ScheduleMsgDal(); - ScheduleMsg msg = new ScheduleMsg(); - msg.MsgDetail = ex.Message; - msg.HappenTime = DateTime.Now; - msg.MsgType = 5;// 1 成功 5异常, - msg.ScheduleTypeId = schedule.ScheduleTypeId; - _msgDal.InsertScheduleMsg(ctx, msg); - + Logger.Error($"服务器插件:{schedule.Name}", ex.Message, ex); + } + finally + { + Logger.Info(schedule.Name, $"成功{succeedNum}条,失败{failNum}条"); + Logger.Info(schedule.Name, $"销售出库单自动下推应付单end..."); } - - } diff --git a/CY.SAL_OUTSTOCK/CY.SAL_OUTSTOCK.csproj b/CY.SAL_OUTSTOCK/CY.SAL_OUTSTOCK.csproj index bc5c31d..63ae828 100644 --- a/CY.SAL_OUTSTOCK/CY.SAL_OUTSTOCK.csproj +++ b/CY.SAL_OUTSTOCK/CY.SAL_OUTSTOCK.csproj @@ -49,6 +49,10 @@ ..\..\..\..\..\Program Files (x86)\Kingdee\K3Cloud\WebSite\bin\Kingdee.BOS.DataEntity.dll + + False + ..\..\..\..\..\Program Files (x86)\Kingdee\K3Cloud\WebSite\bin\Kingdee.BOS.ServiceHelper.dll + ..\..\..\..\..\Program Files (x86)\Kingdee\K3Cloud\WebSite\bin\Kingdee.K3.BD.Contracts.dll @@ -64,6 +68,7 @@ + diff --git a/CY.SAL_OUTSTOCK/PushSaleOutBillPlugIn.cs b/CY.SAL_OUTSTOCK/PushSaleOutBillPlugIn.cs new file mode 100644 index 0000000..32e437b --- /dev/null +++ b/CY.SAL_OUTSTOCK/PushSaleOutBillPlugIn.cs @@ -0,0 +1,195 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Kingdee.BOS; +using Kingdee.BOS.Core.Bill.PlugIn; +using Kingdee.BOS.Core.DynamicForm.PlugIn.Args; +using Kingdee.BOS.Core.List; +using Kingdee.BOS.Core.List.PlugIn; +using Kingdee.BOS.ServiceHelper; +using Kingdee.BOS.Util; +using Kingdee.BOS.WebApi.FormService; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System.ComponentModel; +using Kingdee.BOS.Core.DynamicForm; +using Kingdee.BOS.App; +using Kingdee.BOS.Contracts; +using Kingdee.BOS.Core.Metadata; +using Kingdee.BOS.Core.DynamicForm.Operation; +using Kingdee.BOS.Orm.DataEntity; +using Kingdee.BOS.Core.Metadata.ConvertElement.ServiceArgs; +using Kingdee.BOS.Core.Metadata.ConvertElement; +using Kingdee.BOS.Orm; +using Kingdee.BOS.App.Data; +using System.Data; +using Kingdee.BOS.Log; +using Kingdee.BOS.Core.Metadata.FieldElement; + +namespace KD.K3.QQSD.PlugIn +{ + [Description("批量下推生成销售出库单插件")] + public class PushSaleOutBillPlugIn : AbstractListPlugIn + { + long sScrId = 0; + string sScrBillNo = ""; + public override void BarItemClick(BarItemClickEventArgs e) + { + base.BarItemClick(e); + long sOutId = 0;//珠海分布式调出单单号内码 + string sOutBillNo = "";//珠海分布式调出单单号 + bool flag = true; + string sBillNo = ""; + long sEntryId = 0; + long slevel = 2; + long sId = 0; + if (e.BarItemKey == "tbPushSalOut")//批量下推调拨 + { + ListSelectedRowCollection rows = this.ListView.SelectedRowsInfo; + List pkIds = new List(); + List pkEntryIds = new List(); + if (rows.Count <= 0) + { + this.View.ShowMessage("请选择对应的发货通知单!!!"); + return; + } + foreach (var row in rows) + { + sBillNo = row.BillNo.ToString();//发货通知单号 + sId = Convert.ToInt64(row.PrimaryKeyValue);//发货通知单ID + sEntryId = Convert.ToInt64(row.EntryPrimaryKeyValue);//发货通知单ID + string sSql = "select FID from T_SAL_DELIVERYNOTICEENTRY where FID= " + sId + " and FENTRYID= " + sEntryId + " and abs(FBaseUnitQty) > abs(FBASEJOINOUTQTY) "; + sSql = String.Format(@"/*dialect*/" + sSql); + var dt = DBServiceHelper.ExecuteDynamicObject(this.Context, sSql); + if (dt.Count > 0) + { + string getSourceSql = "select FID from T_SAL_DELIVERYNOTICE where FBILLNO='" + sBillNo + "'"; + IOperationResult result = Invoke("SAL_DELIVERYNOTICE", "SAL_OUTSTOCK", getSourceSql, "ad0779a4685a43a08f08d2e42d7bf3e9"); + } + }//进入下一个循环生成下一个系列的分布式调出单 + if (flag) + { + this.View.ShowMessage("生成对应系列的分布式调出单完成!!!"); + } + } + } + private IOperationResult Invoke(string source, string target, string getSourceSql, string sargetBillTypeId) + { + try { + IOperationResult result = new OperationResult(); + //获取单据转换规则 + ConvertRuleElement ruleElement = ServiceHelper.GetService().GetConvertRules(this.Context, source, target).FirstOrDefault(); + + //如下代码 直接通过查询数据库获取单据转换源单数据 + ListSelectedRowCollection rows = new ListSelectedRowCollection(); + int i = 0; + using (IDataReader reader = DBUtils.ExecuteReader(this.Context, getSourceSql)) + { + while (reader.Read()) + { + ListSelectedRow row = new ListSelectedRow(reader["FID"].ToString(), string.Empty, i++, source); + rows.Add(row); + } + } + + PushArgs pushArgs = new PushArgs(ruleElement, rows.ToArray()); + pushArgs.TargetBillTypeId = sargetBillTypeId;//单据类型 + //转换生成目标单 + ConvertOperationResult convertResult = ServiceHelper.GetService().Push(this.Context, pushArgs); + ////合并转换操作结果 + //result.MergeResult(convertResult); + + ////目标单据数据集合 + DynamicObject[] destObjs = convertResult.TargetDataEntities.Select(r => r.DataEntity).ToArray(); + //根据实际情况,处理目标单据数据 + //destObjs[0]["Date"] = Convert.ToDateTime(sDate); + //DynamicObjectCollection col_FEntityDetail; + //////if (target == "SAL_OUTSTOCK")//销售出库 + //////{ + //col_FEntityDetail = destObjs[0]["SAL_OUTSTOCKENTRY"] as DynamicObjectCollection; + //////} + //////else + //////{//销售退货 + ////// col_FEntityDetail = destObjs[0]["SAL_RETURNSTOCKENTRY"] as DynamicObjectCollection; + //////} + ////#region + //long sStockOrgID = 0; + //sStockOrgID = Convert.ToInt64(destObjs[0]["StockOrgId_Id"]); + + + //foreach (var item in col_FEntityDetail) + //{ + // //item["KeeperID_Id"] = item["OwnerID_Id"];//保管者 + + // string sStockSql = "select FOrgStockId from v_BusinessOrgId where FORGID= " + sStockOrgID + " "; + // sStockSql = String.Format(@"/*dialect*/" + sStockSql); + // var dt = DBServiceHelper.ExecuteDynamicObject(this.Context, sStockSql); + + // //if (dt.Count > 0 && Convert.ToInt64(dt[0]["FOrgStockId"]) != 0) + // if (dt.Count > 0) + // { + // //var targetBillMeta = ServiceHelper.GetService().Load(this.Context, target) as FormMetadata; + // //BusinessInfo info = targetBillMeta.BusinessInfo; + // //BaseDataField stockFld = info.GetField("FStockId") as BaseDataField; + // //long stockId = Convert.ToInt64(dt[0]["FOrgStockId"]); + // //IViewService viewService = ServiceHelper.GetService(); + // //DynamicObject[] stockObjs = viewService.LoadFromCache(this.Context, new object[] { stockId }, stockFld.RefFormDynamicObjectType); + // //stockFld.RefIDDynamicProperty.SetValue(item, stockId); + // //stockFld.DynamicProperty.SetValue(item, stockObjs[0]); + + // item["StockID_Id"] = Convert.ToInt64(dt[0]["FOrgStockId"]); + // } + //} + //#endregion + + ////目标单元数据 + FormMetadata destFormMetadata = ServiceHelper.GetService().Load(this.Context, target) as FormMetadata; + + ////保存目标单据 + IOperationResult saveResult = ServiceHelper.GetService().Save(this.Context, destFormMetadata.BusinessInfo, destObjs, OperateOption.Create()); + ////合并保存操作结果 + //result.MergeResult(saveResult); + //根据操作结果构造返回结果 + if ((saveResult.ValidationErrors != null && saveResult.ValidationErrors.Count > 0)) + //|| (result.OperateResult != null && result.OperateResult.Count > 0)) + { + var errorInfo = string.Join(";", saveResult.ValidationErrors.Select(x => x.Message)); + //this.View.ShowErrMessage("调用下推, 导致自动保存失败 原因:" + errorInfo); + + //result.IsSuccess = false; + //this.View.ShowErrMessage("调用下推, 导致自动保存失败 原因:" + saveResult.ValidationErrors[0].Message.ToString()); + throw new KDBusinessException("", "未知原因导致自动保存失败原因:" + errorInfo); + } + //this.View.ShowMessage("1"); + // 取到需要自动提交、审核的单据内码 + object[] pkArray = (from p in destObjs select p[0]).ToArray(); + //设置提交参数 + IOperationResult submitResult = ServiceHelper.GetService().Submit(this.Context, destFormMetadata.BusinessInfo, pkArray, "Submit", OperateOption.Create()); + + // 判断提交结果,如果失败,则内部会抛出错误,回滚代码 + if (submitResult.IsSuccess == false) + { + throw new KDBusinessException("", "未知原因导致自动提交失败!"); + } + //设置审核参数 + IOperationResult auditResult = ServiceHelper.GetService().Audit(this.Context, destFormMetadata.BusinessInfo, pkArray, OperateOption.Create()); + // 判断提交结果,如果失败,则内部会抛出错误,回滚代码 + if (auditResult.IsSuccess == false) + { + throw new KDBusinessException("", "未知原因导致自动审核失败!"); + } + //显示下推后的单据 + //ShowPushResult("k0f9e182dbc5247fcabc9479ddb300fa3", convertResult, destObjs); + return result; + } + catch (Exception ex) + { + Logger.Error("同步报关信息时", "同步报关信息时 error:" + ex.Message + ex.StackTrace, ex); + throw ex; + } + + } + + } +} diff --git a/CY.SAL_OUTSTOCK/SQLServer/无关联应收单.sql b/CY.SAL_OUTSTOCK/SQLServer/无关联应收单.sql index 44ec231..023291c 100644 --- a/CY.SAL_OUTSTOCK/SQLServer/无关联应收单.sql +++ b/CY.SAL_OUTSTOCK/SQLServer/无关联应收单.sql @@ -8,7 +8,6 @@ SELECT ,A.FBILLNO ,A.FSTOCKORGID ,AE.FENTRYID - ,B.FID FROM T_SAL_OUTSTOCK A LEFT JOIN T_SAL_OUTSTOCKENTRY AE ON A.FID = AE.FID diff --git a/CY.SAL_OUTSTOCK/TestAutoPushPlugIn.cs b/CY.SAL_OUTSTOCK/TestAutoPushPlugIn.cs new file mode 100644 index 0000000..e7860d4 --- /dev/null +++ b/CY.SAL_OUTSTOCK/TestAutoPushPlugIn.cs @@ -0,0 +1,125 @@ +using Kingdee.BOS.App.Core.ScheduleService; +using Kingdee.BOS.App.Data; +using Kingdee.BOS.Contracts; +using Kingdee.BOS.Core.DynamicForm.Operation; +using Kingdee.BOS.Core.List; +using Kingdee.BOS.Core.Metadata.ConvertElement.ServiceArgs; +using Kingdee.BOS.Core; +using Kingdee.BOS.Orm.DataEntity; +using Kingdee.BOS.Orm; +using Kingdee.BOS.Util; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Kingdee.BOS; +using System.ComponentModel; +using Kingdee.BOS.Core.List.PlugIn; +using Kingdee.BOS.Core.DynamicForm.PlugIn.Args; +using Kingdee.BOS.Core.Metadata; +using Kingdee.BOS.ServiceHelper; +using Kingdee.BOS.Core.Metadata.FieldElement; +using Kingdee.BOS.App; +using Kingdee.BOS.Core.DynamicForm; + +namespace CY.SAL_OUTSTOCK +{ + [Description("测试自动下推功能"), HotUpdate] + public class TestAutoPushPlugIn : AbstractListPlugIn + { + + + public override void BarItemClick(BarItemClickEventArgs e) + { + base.BarItemClick(e); + + if (e.BarItemKey.Equals("tbTestAutoP")) + { + Run(this.Context); + } + } + + public void Run(Context ctx) + { + + try + { + IConvertService service = Kingdee.BOS.App.ServiceHelper.GetService(); + + string sourceFormId = "SAL_OUTSTOCK"; + + string targetFormId = "AR_RECEIVABLE"; + string targetBillTypeId = "180ecd4afd5d44b5be78a6efe4a7e041"; + //var rules = service.GetConvertRules(ctx, sourceFormId, targetFormId); + + string convertRuleId = "AR_OutStockToReceivableMap"; //销售出库单下推应付单 + + var ruleMeta = service.GetConvertRule(ctx, convertRuleId); + + var rule = ruleMeta.Rule; + var dbList = GetDBData(ctx); + if (dbList != null && dbList.Any()) + { + var groupbyList = dbList.GroupBy(x => x["FBILLNO"]); + StringBuilder stringBuilder = new StringBuilder(); + foreach (var list in groupbyList) + { + var pkid = dbList.Select(x => x["FID"]).ToArray(); + List selectedRows = list.Select(x => new ListSelectedRow(x["FID"].ToString(), x["FENTRYID"].ToString(), 0, sourceFormId)).ToList(); + PushArgs pushArgs = new PushArgs(rule, selectedRows.ToArray());//下推入口参数 + pushArgs.TargetBillTypeId = targetBillTypeId; + OperateOption option = OperateOption.Create();//选项参数 + + try + { + ConvertOperationResult convertResult = service.Push(ctx, pushArgs, option); + + DynamicObject[] destObjs = convertResult.TargetDataEntities.Select(r => r.DataEntity).ToArray(); + + FormMetadata destFormMetadata = ServiceHelper.GetService().Load(this.Context, targetFormId) as FormMetadata; + + IOperationResult saveResult = ServiceHelper.GetService().Save(this.Context, destFormMetadata.BusinessInfo, destObjs, OperateOption.Create()); + + if ((saveResult.ValidationErrors != null && saveResult.ValidationErrors.Count > 0)) + { + var errorInfo = string.Join(";", saveResult.ValidationErrors.Select(x => x.Message)); + + throw new KDBusinessException("", "未知原因导致自动保存失败原因:" + errorInfo); + } + } + catch (KDBusinessException ex) + { + stringBuilder.AppendLine($"单据:{list.Key}{ex.GetErrorInfo()}"); + } + } + + if (!stringBuilder.IsNullOrEmpty()) + throw new Exception(stringBuilder.ToString()); + } + } + catch (Exception ex) + { + //ScheduleMsgDal _msgDal = new ScheduleMsgDal(); + //ScheduleMsg msg = new ScheduleMsg(); + //msg.MsgDetail = ex.Message; + //msg.HappenTime = DateTime.Now; + //msg.MsgType = 5;// 1 成功 5异常, + //msg.ScheduleTypeId = schedule.ScheduleTypeId; + //_msgDal.InsertScheduleMsg(ctx, msg); + + } + + } + + + private DynamicObjectCollection GetDBData(Context ctx) + { + var unSql = $@" +select * from V_NOT_RECEIVABLE_OUTSTOCK +"; + var dbList = DBUtils.ExecuteDynamicObject(ctx, $"/*dialect*/{unSql}"); + + return dbList; + } + } +} diff --git a/GateDge2023.sln b/GateDge2023.sln index b80cc54..48ba309 100644 --- a/GateDge2023.sln +++ b/GateDge2023.sln @@ -31,7 +31,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "旭东", "旭东", "{0C4E3D EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "汇威", "汇威", "{42311C80-7B4C-4353-BCA9-4ABD024290C8}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kingdee.K3.SCM.App.Sal.Report.PlugInEx", "Kingdee.K3.SCM.Sal.Report.PlugInEx\Kingdee.K3.SCM.App.Sal.Report.PlugInEx.csproj", "{01F02D15-2726-4077-80FC-9E38EF29BABC}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HW.App.Sal.Report.PlugInEx", "Kingdee.K3.SCM.Sal.Report.PlugInEx\HW.App.Sal.Report.PlugInEx.csproj", "{01F02D15-2726-4077-80FC-9E38EF29BABC}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "长园", "长园", "{270F576A-EFFF-4728-8E5C-ABDF5C3F3C8B}" EndProject diff --git a/Kingdee.K3.SCM.Sal.Report.PlugInEx/Kingdee.K3.SCM.App.Sal.Report.PlugInEx.csproj b/Kingdee.K3.SCM.Sal.Report.PlugInEx/HW.App.Sal.Report.PlugInEx.csproj similarity index 94% rename from Kingdee.K3.SCM.Sal.Report.PlugInEx/Kingdee.K3.SCM.App.Sal.Report.PlugInEx.csproj rename to Kingdee.K3.SCM.Sal.Report.PlugInEx/HW.App.Sal.Report.PlugInEx.csproj index 5661352..4ecc6c7 100644 --- a/Kingdee.K3.SCM.Sal.Report.PlugInEx/Kingdee.K3.SCM.App.Sal.Report.PlugInEx.csproj +++ b/Kingdee.K3.SCM.Sal.Report.PlugInEx/HW.App.Sal.Report.PlugInEx.csproj @@ -7,11 +7,12 @@ {01F02D15-2726-4077-80FC-9E38EF29BABC} Library Properties - Kingdee.K3.SCM.App.Sal.Report - Kingdee.K3.SCM.App.Sal.Report.PlugInEx - v4.5 + HW.App.Sal.Report.PlugInEx + HW.App.Sal.Report.PlugInEx + v4.0 512 true + true diff --git a/Kingdee.K3.SCM.Sal.Report.PlugInEx/SaleOutStockDetailRptEx.cs b/Kingdee.K3.SCM.Sal.Report.PlugInEx/SaleOutStockDetailRptEx.cs index 88555af..872cb52 100644 --- a/Kingdee.K3.SCM.Sal.Report.PlugInEx/SaleOutStockDetailRptEx.cs +++ b/Kingdee.K3.SCM.Sal.Report.PlugInEx/SaleOutStockDetailRptEx.cs @@ -1,4 +1,5 @@ -using Kingdee.BOS.Core.Report; +using Kingdee.BOS; +using Kingdee.BOS.Core.Report; using Kingdee.BOS.Util; using Kingdee.K3.SCM.App.Sal.Report; using System; @@ -6,10 +7,11 @@ using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Linq; +using System.Net; using System.Text; using System.Threading.Tasks; -namespace Kingdee.K3.SCM.App.Sal.ReportEx +namespace HW.App.Sal.Report.PlugInEx { [Description("销售出库明细报表数据源插件-扩展"), HotUpdate] public class SaleOutStockDetailRptEx : SaleOutStockDetailRpt @@ -36,7 +38,11 @@ namespace Kingdee.K3.SCM.App.Sal.ReportEx protected override DataTable GetReportData(string tablename, IRptParams filter) { - return base.GetReportData(tablename, filter); + var dataTable = base.GetReportData(tablename, filter); + + + var sql = @"select "; + return dataTable; } public override void CloseReport() @@ -46,7 +52,11 @@ namespace Kingdee.K3.SCM.App.Sal.ReportEx public override ReportHeader GetReportHeaders(IRptParams filter) { - return base.GetReportHeaders(filter); + var header = base.GetReportHeaders(filter); + + //header.AddChild("FSALESCATEGORY", new LocaleValue("销售类别")); + + return header; } } } diff --git a/SAL_OUTSTOCK/SAL_OUTSTOCK.csproj b/SAL_OUTSTOCK/SAL_OUTSTOCK.csproj index 098ec69..c9044bc 100644 --- a/SAL_OUTSTOCK/SAL_OUTSTOCK.csproj +++ b/SAL_OUTSTOCK/SAL_OUTSTOCK.csproj @@ -49,6 +49,7 @@ + diff --git a/SAL_OUTSTOCK/Utils/HttpWebHelper.cs b/SAL_OUTSTOCK/Utils/HttpWebHelper.cs index cc30191..9919b40 100644 --- a/SAL_OUTSTOCK/Utils/HttpWebHelper.cs +++ b/SAL_OUTSTOCK/Utils/HttpWebHelper.cs @@ -6,6 +6,8 @@ using System.Net.Security; using System.Net; using System.Security.Cryptography.X509Certificates; using System.Text; +using System.Web; +using Kingdee.BOS.Http; namespace SAL_OUTSTOCK.Utils { diff --git a/UnitTestProject1/HttpWebHelper.cs b/UnitTestProject1/HttpWebHelper.cs new file mode 100644 index 0000000..ae13c07 --- /dev/null +++ b/UnitTestProject1/HttpWebHelper.cs @@ -0,0 +1,100 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net.Security; +using System.Net; +using System.Security.Cryptography.X509Certificates; +using System.Text; +using System.Web; + +namespace SAL_OUTSTOCK.Utils +{ + public static class HttpWebHelper + { + /// + /// post请求 + /// + /// 请求地址 + /// 请求数据 + /// 证书 + /// + public static string DoPost(string url, string postData, X509Certificate2 certificate2) + { + try + { + string result = string.Empty; + + HttpWebRequest request = null; + if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase)) + { + request = WebRequest.Create(url) as HttpWebRequest; + ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult); + request.ProtocolVersion = HttpVersion.Version11; + // 这里设置了协议类型。 + ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;// SecurityProtocolType.Tls1.2; + request.KeepAlive = false; + ServicePointManager.CheckCertificateRevocationList = true; + ServicePointManager.DefaultConnectionLimit = 100; + ServicePointManager.Expect100Continue = false; + } + else + { + request = (HttpWebRequest)WebRequest.Create(url); + } + + //string baseDirectory = AppDomain.CurrentDomain.BaseDirectory; + + ////证书 + //var keystorefile = baseDirectory + @"\bin\ISSUE\testISSUE.pfx"; + //var key = "123456"; + //var cer = new X509Certificate2(keystorefile, key); + + if (certificate2 != null) + request.ClientCertificates.Add(certificate2); + + request.Method = "POST"; //使用get方式发送数据 + request.ContentType = "application/json;charset=utf-8"; + + byte[] data = Encoding.UTF8.GetBytes(postData); + Stream newStream = request.GetRequestStream(); + newStream.Write(data, 0, data.Length); + newStream.Close(); + + HttpWebResponse response = (HttpWebResponse)request.GetResponse(); + Stream stream = response.GetResponseStream(); + + using (StreamReader sr = new StreamReader(stream)) + { + result = sr.ReadToEnd(); + } + return result; + } + + catch (Exception ex) + { + throw ex; + } + + } + + /// + /// post请求 + /// + /// + /// + /// + public static string DoPost(string url, string postData) + { + return DoPost(url, postData, null); + } + + private static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors) + { + if (errors == SslPolicyErrors.None) + return true; //总是接受 + + return false; + } + } +} diff --git a/UnitTestProject1/PushSaleOutBillPlugIn.cs b/UnitTestProject1/PushSaleOutBillPlugIn.cs new file mode 100644 index 0000000..32e437b --- /dev/null +++ b/UnitTestProject1/PushSaleOutBillPlugIn.cs @@ -0,0 +1,195 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Kingdee.BOS; +using Kingdee.BOS.Core.Bill.PlugIn; +using Kingdee.BOS.Core.DynamicForm.PlugIn.Args; +using Kingdee.BOS.Core.List; +using Kingdee.BOS.Core.List.PlugIn; +using Kingdee.BOS.ServiceHelper; +using Kingdee.BOS.Util; +using Kingdee.BOS.WebApi.FormService; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System.ComponentModel; +using Kingdee.BOS.Core.DynamicForm; +using Kingdee.BOS.App; +using Kingdee.BOS.Contracts; +using Kingdee.BOS.Core.Metadata; +using Kingdee.BOS.Core.DynamicForm.Operation; +using Kingdee.BOS.Orm.DataEntity; +using Kingdee.BOS.Core.Metadata.ConvertElement.ServiceArgs; +using Kingdee.BOS.Core.Metadata.ConvertElement; +using Kingdee.BOS.Orm; +using Kingdee.BOS.App.Data; +using System.Data; +using Kingdee.BOS.Log; +using Kingdee.BOS.Core.Metadata.FieldElement; + +namespace KD.K3.QQSD.PlugIn +{ + [Description("批量下推生成销售出库单插件")] + public class PushSaleOutBillPlugIn : AbstractListPlugIn + { + long sScrId = 0; + string sScrBillNo = ""; + public override void BarItemClick(BarItemClickEventArgs e) + { + base.BarItemClick(e); + long sOutId = 0;//珠海分布式调出单单号内码 + string sOutBillNo = "";//珠海分布式调出单单号 + bool flag = true; + string sBillNo = ""; + long sEntryId = 0; + long slevel = 2; + long sId = 0; + if (e.BarItemKey == "tbPushSalOut")//批量下推调拨 + { + ListSelectedRowCollection rows = this.ListView.SelectedRowsInfo; + List pkIds = new List(); + List pkEntryIds = new List(); + if (rows.Count <= 0) + { + this.View.ShowMessage("请选择对应的发货通知单!!!"); + return; + } + foreach (var row in rows) + { + sBillNo = row.BillNo.ToString();//发货通知单号 + sId = Convert.ToInt64(row.PrimaryKeyValue);//发货通知单ID + sEntryId = Convert.ToInt64(row.EntryPrimaryKeyValue);//发货通知单ID + string sSql = "select FID from T_SAL_DELIVERYNOTICEENTRY where FID= " + sId + " and FENTRYID= " + sEntryId + " and abs(FBaseUnitQty) > abs(FBASEJOINOUTQTY) "; + sSql = String.Format(@"/*dialect*/" + sSql); + var dt = DBServiceHelper.ExecuteDynamicObject(this.Context, sSql); + if (dt.Count > 0) + { + string getSourceSql = "select FID from T_SAL_DELIVERYNOTICE where FBILLNO='" + sBillNo + "'"; + IOperationResult result = Invoke("SAL_DELIVERYNOTICE", "SAL_OUTSTOCK", getSourceSql, "ad0779a4685a43a08f08d2e42d7bf3e9"); + } + }//进入下一个循环生成下一个系列的分布式调出单 + if (flag) + { + this.View.ShowMessage("生成对应系列的分布式调出单完成!!!"); + } + } + } + private IOperationResult Invoke(string source, string target, string getSourceSql, string sargetBillTypeId) + { + try { + IOperationResult result = new OperationResult(); + //获取单据转换规则 + ConvertRuleElement ruleElement = ServiceHelper.GetService().GetConvertRules(this.Context, source, target).FirstOrDefault(); + + //如下代码 直接通过查询数据库获取单据转换源单数据 + ListSelectedRowCollection rows = new ListSelectedRowCollection(); + int i = 0; + using (IDataReader reader = DBUtils.ExecuteReader(this.Context, getSourceSql)) + { + while (reader.Read()) + { + ListSelectedRow row = new ListSelectedRow(reader["FID"].ToString(), string.Empty, i++, source); + rows.Add(row); + } + } + + PushArgs pushArgs = new PushArgs(ruleElement, rows.ToArray()); + pushArgs.TargetBillTypeId = sargetBillTypeId;//单据类型 + //转换生成目标单 + ConvertOperationResult convertResult = ServiceHelper.GetService().Push(this.Context, pushArgs); + ////合并转换操作结果 + //result.MergeResult(convertResult); + + ////目标单据数据集合 + DynamicObject[] destObjs = convertResult.TargetDataEntities.Select(r => r.DataEntity).ToArray(); + //根据实际情况,处理目标单据数据 + //destObjs[0]["Date"] = Convert.ToDateTime(sDate); + //DynamicObjectCollection col_FEntityDetail; + //////if (target == "SAL_OUTSTOCK")//销售出库 + //////{ + //col_FEntityDetail = destObjs[0]["SAL_OUTSTOCKENTRY"] as DynamicObjectCollection; + //////} + //////else + //////{//销售退货 + ////// col_FEntityDetail = destObjs[0]["SAL_RETURNSTOCKENTRY"] as DynamicObjectCollection; + //////} + ////#region + //long sStockOrgID = 0; + //sStockOrgID = Convert.ToInt64(destObjs[0]["StockOrgId_Id"]); + + + //foreach (var item in col_FEntityDetail) + //{ + // //item["KeeperID_Id"] = item["OwnerID_Id"];//保管者 + + // string sStockSql = "select FOrgStockId from v_BusinessOrgId where FORGID= " + sStockOrgID + " "; + // sStockSql = String.Format(@"/*dialect*/" + sStockSql); + // var dt = DBServiceHelper.ExecuteDynamicObject(this.Context, sStockSql); + + // //if (dt.Count > 0 && Convert.ToInt64(dt[0]["FOrgStockId"]) != 0) + // if (dt.Count > 0) + // { + // //var targetBillMeta = ServiceHelper.GetService().Load(this.Context, target) as FormMetadata; + // //BusinessInfo info = targetBillMeta.BusinessInfo; + // //BaseDataField stockFld = info.GetField("FStockId") as BaseDataField; + // //long stockId = Convert.ToInt64(dt[0]["FOrgStockId"]); + // //IViewService viewService = ServiceHelper.GetService(); + // //DynamicObject[] stockObjs = viewService.LoadFromCache(this.Context, new object[] { stockId }, stockFld.RefFormDynamicObjectType); + // //stockFld.RefIDDynamicProperty.SetValue(item, stockId); + // //stockFld.DynamicProperty.SetValue(item, stockObjs[0]); + + // item["StockID_Id"] = Convert.ToInt64(dt[0]["FOrgStockId"]); + // } + //} + //#endregion + + ////目标单元数据 + FormMetadata destFormMetadata = ServiceHelper.GetService().Load(this.Context, target) as FormMetadata; + + ////保存目标单据 + IOperationResult saveResult = ServiceHelper.GetService().Save(this.Context, destFormMetadata.BusinessInfo, destObjs, OperateOption.Create()); + ////合并保存操作结果 + //result.MergeResult(saveResult); + //根据操作结果构造返回结果 + if ((saveResult.ValidationErrors != null && saveResult.ValidationErrors.Count > 0)) + //|| (result.OperateResult != null && result.OperateResult.Count > 0)) + { + var errorInfo = string.Join(";", saveResult.ValidationErrors.Select(x => x.Message)); + //this.View.ShowErrMessage("调用下推, 导致自动保存失败 原因:" + errorInfo); + + //result.IsSuccess = false; + //this.View.ShowErrMessage("调用下推, 导致自动保存失败 原因:" + saveResult.ValidationErrors[0].Message.ToString()); + throw new KDBusinessException("", "未知原因导致自动保存失败原因:" + errorInfo); + } + //this.View.ShowMessage("1"); + // 取到需要自动提交、审核的单据内码 + object[] pkArray = (from p in destObjs select p[0]).ToArray(); + //设置提交参数 + IOperationResult submitResult = ServiceHelper.GetService().Submit(this.Context, destFormMetadata.BusinessInfo, pkArray, "Submit", OperateOption.Create()); + + // 判断提交结果,如果失败,则内部会抛出错误,回滚代码 + if (submitResult.IsSuccess == false) + { + throw new KDBusinessException("", "未知原因导致自动提交失败!"); + } + //设置审核参数 + IOperationResult auditResult = ServiceHelper.GetService().Audit(this.Context, destFormMetadata.BusinessInfo, pkArray, OperateOption.Create()); + // 判断提交结果,如果失败,则内部会抛出错误,回滚代码 + if (auditResult.IsSuccess == false) + { + throw new KDBusinessException("", "未知原因导致自动审核失败!"); + } + //显示下推后的单据 + //ShowPushResult("k0f9e182dbc5247fcabc9479ddb300fa3", convertResult, destObjs); + return result; + } + catch (Exception ex) + { + Logger.Error("同步报关信息时", "同步报关信息时 error:" + ex.Message + ex.StackTrace, ex); + throw ex; + } + + } + + } +} diff --git a/UnitTestProject1/UnitTest1.cs b/UnitTestProject1/UnitTest1.cs index 36583cc..32d5b0a 100644 --- a/UnitTestProject1/UnitTest1.cs +++ b/UnitTestProject1/UnitTest1.cs @@ -1,6 +1,14 @@ using ExtensionMethods; using Microsoft.VisualStudio.TestTools.UnitTesting; +using Newtonsoft.Json; +using SAL_OUTSTOCK.Utils; using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Net.Sockets; +using System.Security.Cryptography; +using System.Text; namespace UnitTestProject1 { @@ -11,14 +19,131 @@ namespace UnitTestProject1 public void TestMethod1() { - object ttt = " "; + string appKey = "437268ee6e1a44b6ba135eea1614f94d"; + string secret = "72CD0295-2312-4B08-9A4C-2A338A0EE9BF"; + // 业务参数 + Dictionary jsonMap = new Dictionary(); + jsonMap.Add("declaCode", "T00001"); + jsonMap.Add("entCusCode", "4404660006"); + jsonMap.Add("entCreditCode", "91440404MABRGQJR1H"); + jsonMap.Add("entName", "珠海昶展物流有限公司"); + jsonMap.Add("declaEntCusCode", "4404660006"); + jsonMap.Add("declaEntCreditCode", "91440404MABRGQJR1H"); + jsonMap.Add("declaEntName", "珠海昶展物流有限公司"); + jsonMap.Add("customsCode", "5781"); + jsonMap.Add("bookNum", "T5781W000004"); + jsonMap.Add("compileDate", "1970-01-01 08:00:00"); + jsonMap.Add("inputMan", "Test01"); + jsonMap.Add("declaType", "00"); + jsonMap.Add("inputDate", "1970-01-01 08:00:00"); + jsonMap.Add("declaDate", "1970-01-01 08:00:00"); - var dd = ttt.ToDecimalR(); + var auditList = new List>(); + Dictionary data = new Dictionary(); + data.Add("itemNo", "1"); + data.Add("deliveryOrderNo", "2"); + data.Add("productCd", "100242"); + data.Add("productDesc", "喇叭"); + data.Add("specificationsModels", " "); + data.Add("deliveryCnt", "80.0000000000"); + data.Add("calcUnit", "Pcs"); + data.Add("hscode", "8"); + data.Add("inventory", "9"); + data.Add("inventoryOrderNo", "10"); + + Dictionary data1 = new Dictionary(); + data1.Add("itemNo", "2"); + data1.Add("deliveryOrderNo", "2"); + data1.Add("productCd", "100243"); + data1.Add("productDesc", "听筒"); + data1.Add("specificationsModels", " "); + data1.Add("deliveryCnt", "80.0000000000"); + data1.Add("calcUnit", "Pcs"); + data1.Add("hscode", "8"); + data1.Add("inventory", "9"); + data1.Add("inventoryOrderNo", "10"); + + + auditList.Add(data); + jsonMap.Add("itemList", auditList); + + string json = JsonConvert.SerializeObject(jsonMap); + json = WebUnit.UrlEncode(json); + + // 系统参数 + Dictionary param = new Dictionary(); + param.Add("name", "supvWarehouse.save"); + param.Add("app_key", appKey); + param.Add("data", json); + param.Add("timestamp", System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); + param.Add("version", ""); + string sign = BuildSign(param, secret); + param.Add("sign", sign); + + var ttt = @"{""entName"":""珠海昶展物流有限公司"",""entCusCode"":""4404660006"",""bookNum"":""T5781W000004"",""declaEntCreditCode"":""91440404MABRGQJR1H"",""deliveryType"":""QTCK"",""declaEntCusCode"":""4404660006"",""inputDate"":""2018-02-02 14:03:07"",""deliveryTm"":""2018-02-09 00:00:00"",""declaType"":""00"",""declaDate"":""2023-12-20 09:38:55"",""declaCode"":""QTCK000003"",""itemList"":[{""productDesc"":""喇叭"",""inventoryOrderNo"":""10"",""deliveryOrderNo"":""2"",""specificationsModels"":"" "",""hscode"":""8"",""deliveryCnt"":""80.0000000000"",""itemNo"":""1"",""inventory"":""9"",""productCd"":""100242"",""calcUnit"":""Pcs""},{""productDesc"":""听筒"",""inventoryOrderNo"":""10"",""deliveryOrderNo"":""2"",""specificationsModels"":"" "",""hscode"":""8"",""deliveryCnt"":""80.0000000000"",""itemNo"":""2"",""inventory"":""9"",""productCd"":""100243"",""calcUnit"":""Pcs""}],""entCreditCode"":""91440404MABRGQJR1H"",""declaEntName"":""珠海昶展物流有限公司"",""inputMan"":""demo"",""customsCode"":""5781""}"; + //var json = "{\"entName\":\"珠海昶展物流有限公司\",\"entCusCode\":\"4404660006\",\"bookNum\":\"T5781W000004\",\"declaEntCreditCode\":\"91440404MABRGQJR1H\",\"declaEntCusCode\":\"4404660006\",\"entCreditCode\":\"91440404MABRGQJR1H\",\"declaEntName\":\"珠海昶展物流有限公司\",\"inputMan\":\"demo\",\"customsCode\":\"5781\",\"inputDate\":\"2018-02-02 14:03:07\",\"declaType\":\"00\",\"deliveryTm\":\"2018-02-09 00:00:00\",\"declaDate\":\"2023-12-20 10:55:59\",\"deliveryType\":\"QTCK\",\"declaCode\":\"QTCK000003\",\"item\":[{\"itemNo\":\"1\",\"deliveryOrderNo\":\"2\",\"productCd\":\"100242\",\"productDesc\":\"喇叭\",\"specificationsModels\":\" \",\"deliveryCnt\":\"80.0000000000\",\"calcUnit\":\"Pcs\",\"hscode\":\"8\",\"inventory\":\"9\",\"inventoryOrderNo\":\"10\"},{\"itemNo\":\"2\",\"deliveryOrderNo\":\"2\",\"productCd\":\"100243\",\"productDesc\":\"听筒\",\"specificationsModels\":\" \",\"deliveryCnt\":\"80.0000000000\",\"calcUnit\":\"Pcs\",\"hscode\":\"8\",\"inventory\":\"9\",\"inventoryOrderNo\":\"10\"}]}"; + + var ttt2 = JsonConvert.SerializeObject(param); + + HttpWebHelper.DoPost("http://119.146.223.48:39082/api/", ttt2); var a = 0.00M; var a2 = 0L; var f = (a == a2); return; } + + public static string BuildSign(Dictionary paramsMap, string secret) + { + //var keySet = paramsMap.Keys; + List paramNames = paramsMap.Keys.ToList(); + paramNames.Sort(); + StringBuilder paramNameValue = new StringBuilder(); + foreach (var paramName in paramNames) + { + paramNameValue.Append(paramName).Append(paramsMap[paramName]); + } + string source = secret + paramNameValue.ToString() + secret; + return ToMD5(source); + } + + public static string ToMD5(string message) + { + try + { + // 1 创建一个提供信息摘要算法的对象,初始化为md5算法对象 + MD5 md5 = new MD5CryptoServiceProvider(); + // 2 将消息变成byte数组 + byte[] input = Encoding.UTF8.GetBytes(message); + // 3 计算后获得字节数组,这就是那128位了 + byte[] buff = md5.ComputeHash(input); + // 4 把数组每一字节(一个字节占八位)换成16进制连成md5字符串 + return Byte2hex(buff); + } + catch (Exception e) + { + throw e; + } + } + + private static string Byte2hex(byte[] bytes) + { + //创建一个StringBuilder对象来存储最终的结果 + StringBuilder sign = new StringBuilder(); + //使用for循环遍历字节数组中的每个字节 + for (int i = 0; i < bytes.Length; i++) + { + // 将字节强制转换为整数,并对其进行位运算,即保留后八位的值,并转换为十六进制形式的字符串 + string hex = bytes[i].ToString("x2"); + // 如果转换后的字符串长度为1,即只有1位,则在前面添加一个0,以保证每个字节都是两位十六进制数 + if (hex.Length == 1) + { + sign.Append("0"); + } + // 将转换后的字符串追加到StringBuilder对象中,并转换为大写形式 + sign.Append(hex.ToUpper()); + } + return sign.ToString(); + } } } diff --git a/UnitTestProject1/UnitTestProject1.csproj b/UnitTestProject1/UnitTestProject1.csproj index 017bd92..59ad12e 100644 --- a/UnitTestProject1/UnitTestProject1.csproj +++ b/UnitTestProject1/UnitTestProject1.csproj @@ -45,12 +45,21 @@ ..\packages\MSTest.TestFramework.2.2.10\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll + + False + ..\..\..\..\..\Program Files (x86)\Kingdee\K3Cloud\WebSite\bin\Newtonsoft.Json.dll + + + ..\..\..\..\..\Program Files (x86)\Kingdee\K3Cloud\WebSite\bin\System.Net.Http.dll + + + diff --git a/UnitTestProject1/WebUnit.cs b/UnitTestProject1/WebUnit.cs new file mode 100644 index 0000000..4b513bb --- /dev/null +++ b/UnitTestProject1/WebUnit.cs @@ -0,0 +1,150 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace UnitTestProject1 +{ + public static class WebUnit + { + public static string UrlEncode(string value) + { + if (value == null) + { + return null; + } + + byte[] bytes = Encoding.UTF8.GetBytes(value); + return Encoding.UTF8.GetString(UrlEncode(bytes, 0, bytes.Length, alwaysCreateNewReturnValue: false)); + } + + private static byte[] UrlEncode(byte[] bytes, int offset, int count, bool alwaysCreateNewReturnValue) + { + byte[] array = UrlEncode(bytes, offset, count); + if (!alwaysCreateNewReturnValue || array == null || array != bytes) + { + return array; + } + + return (byte[])array.Clone(); + } + + private static byte[] UrlEncode(byte[] bytes, int offset, int count) + { + if (!ValidateUrlEncodingParameters(bytes, offset, count)) + { + return null; + } + + int num = 0; + int num2 = 0; + for (int i = 0; i < count; i++) + { + char c = (char)bytes[offset + i]; + if (c == ' ') + { + num++; + } + else if (!IsUrlSafeChar(c)) + { + num2++; + } + } + + if (num == 0 && num2 == 0) + { + if (offset == 0 && bytes.Length == count) + { + return bytes; + } + + byte[] array = new byte[count]; + Buffer.BlockCopy(bytes, offset, array, 0, count); + return array; + } + + byte[] array2 = new byte[count + num2 * 2]; + int num3 = 0; + for (int j = 0; j < count; j++) + { + byte b = bytes[offset + j]; + char c2 = (char)b; + if (IsUrlSafeChar(c2)) + { + array2[num3++] = b; + continue; + } + + if (c2 == ' ') + { + array2[num3++] = 43; + continue; + } + + array2[num3++] = 37; + array2[num3++] = (byte)IntToHex((b >> 4) & 0xF); + array2[num3++] = (byte)IntToHex(b & 0xF); + } + + return array2; + } + + private static char IntToHex(int n) + { + if (n <= 9) + { + return (char)(n + 48); + } + + return (char)(n - 10 + 65); + } + + private static bool ValidateUrlEncodingParameters(byte[] bytes, int offset, int count) + { + if (bytes == null && count == 0) + { + return false; + } + + if (bytes == null) + { + throw new ArgumentNullException("bytes"); + } + + if (offset < 0 || offset > bytes.Length) + { + throw new ArgumentOutOfRangeException("offset"); + } + + if (count < 0 || offset + count > bytes.Length) + { + throw new ArgumentOutOfRangeException("count"); + } + + return true; + } + + private static bool IsUrlSafeChar(char ch) + { + if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9')) + { + return true; + } + + switch (ch) + { + case '!': + case '(': + case ')': + case '*': + case '-': + case '.': + case '_': + return true; + default: + return false; + } + } + } +}