From 2cbb772c2c1f0b8ee6b9f4dc1bf6c804063d3714 Mon Sep 17 00:00:00 2001 From: xiongshuai <873144595@qq.com> Date: Thu, 11 Dec 2025 22:28:43 +0800 Subject: [PATCH] =?UTF-8?q?=E9=94=80=E5=94=AE=E5=A2=9E=E5=80=BC=E7=A8=8E?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BB=A5=E5=8F=8Asx=E5=90=88=E5=90=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ServicePlugIn/AfterSave.cs | 10 +- Pilot_KD_Parino/AR_SalesVATInvoice/Bill.cs | 28 +++ .../ServicePlugIn/AfterSave.cs | 71 ++++--- Pilot_KD_Parino/Common/CommonHelper.cs | 174 ++++++++++++++---- Pilot_KD_Parino/Pilot_KD_Parino.csproj | 1 + 5 files changed, 207 insertions(+), 77 deletions(-) create mode 100644 Pilot_KD_Parino/AR_SalesVATInvoice/Bill.cs diff --git a/Gatedge.K3.Pilot.PlugIn/BOSPlugIn/AR_SalesVATInvoice/ServicePlugIn/AfterSave.cs b/Gatedge.K3.Pilot.PlugIn/BOSPlugIn/AR_SalesVATInvoice/ServicePlugIn/AfterSave.cs index 389f0b7..58382e5 100644 --- a/Gatedge.K3.Pilot.PlugIn/BOSPlugIn/AR_SalesVATInvoice/ServicePlugIn/AfterSave.cs +++ b/Gatedge.K3.Pilot.PlugIn/BOSPlugIn/AR_SalesVATInvoice/ServicePlugIn/AfterSave.cs @@ -23,13 +23,13 @@ namespace Gatedge.K3.Pilot.PlugIn.BOSPlugIn.AR_SalesVATInvoice.ServicePlugIn e.FieldKeys.Add("FSEQQ"); e.FieldKeys.Add("SRCBILLTYPEID"); // 实体属性名(没有F前缀) e.FieldKeys.Add("SRCBILLNO"); // 实体属性名(没有F前缀) - e.FieldKeys.Add("FSEQ"); + e.FieldKeys.Add("SEQ"); } - public override void AfterExecuteOperationTransaction(AfterExecuteOperationTransaction e) - { - base.AfterExecuteOperationTransaction(e); + public override void EndOperationTransaction(EndOperationTransactionArgs e) + { + base.EndOperationTransaction(e); foreach (var dataEntity in e.DataEntitys) { var billObj = dataEntity as DynamicObject; @@ -88,7 +88,7 @@ WHERE FENTRYID = {entryId}"; else { // FIDD <= 0 时,把当前行FID赋值给FIDD,同时把FSEQ赋值给FSEQQ - var seq = entry["FSEQ"]?.ToString() ?? "0"; + var seq = entry["SEQ"]?.ToString() ?? "0"; var updateSql = $@"/*dialect*/ UPDATE T_IV_SALESICENTRY SET FIDD = {entryId}, diff --git a/Pilot_KD_Parino/AR_SalesVATInvoice/Bill.cs b/Pilot_KD_Parino/AR_SalesVATInvoice/Bill.cs new file mode 100644 index 0000000..633685c --- /dev/null +++ b/Pilot_KD_Parino/AR_SalesVATInvoice/Bill.cs @@ -0,0 +1,28 @@ +using Kingdee.BOS.Core.Bill.PlugIn; +using Kingdee.BOS.Core.DynamicForm.PlugIn.Args; +using Kingdee.BOS.Util; +using System.ComponentModel; + +namespace Pilot_KD_Parino.AR_SalesVATInvoice +{ + [HotUpdate, Description("销售增值税专用发票_表单插件")] + public class Bill : AbstractBillPlugIn + { + public override void AfterDoOperation(AfterDoOperationEventArgs e) + { + base.AfterDoOperation(e); + + string opt = e.Operation.Operation; + + // 保存成功后刷新界面(参考收款核销5的刷新方式) + if (opt == "Save" && e.OperationResult.IsSuccess) + { + // 刷新单据体视图 + this.View.UpdateView("SALESICENTRY"); + // 刷新整个界面 + this.View.Refresh(); + } + } + } +} + diff --git a/Pilot_KD_Parino/AR_SalesVATInvoice/ServicePlugIn/AfterSave.cs b/Pilot_KD_Parino/AR_SalesVATInvoice/ServicePlugIn/AfterSave.cs index 8f412d2..c87eee1 100644 --- a/Pilot_KD_Parino/AR_SalesVATInvoice/ServicePlugIn/AfterSave.cs +++ b/Pilot_KD_Parino/AR_SalesVATInvoice/ServicePlugIn/AfterSave.cs @@ -2,15 +2,14 @@ using Kingdee.BOS; using Kingdee.BOS.Core.DynamicForm.PlugIn; using Kingdee.BOS.Core.DynamicForm.PlugIn.Args; using Kingdee.BOS.Log; +using Kingdee.BOS.Orm; using Kingdee.BOS.Orm.DataEntity; using Kingdee.BOS.ServiceHelper; using Kingdee.BOS.Util; -using Pilot_KD_Parino.Common; using System; using System.ComponentModel; -using System.Linq; -namespace Pilot_KD_Parino.AR_SalesVATInvoice.ServicePlugIn +namespace Gatedge.K3.Pilot.PlugIn.BOSPlugIn.AR_SalesVATInvoice.ServicePlugIn { [HotUpdate, Description("销售增值税专用发票_保存后事件")] public class AfterSave : AbstractOperationServicePlugIn @@ -18,26 +17,25 @@ namespace Pilot_KD_Parino.AR_SalesVATInvoice.ServicePlugIn public override void OnPreparePropertys(PreparePropertysEventArgs e) { base.OnPreparePropertys(e); - // 添加需要加载的字段 - e.FieldKeys.Add("FENTRYID"); + // 根据日志中的实际实体属性名来添加 e.FieldKeys.Add("FIDD"); e.FieldKeys.Add("FSEQQ"); - e.FieldKeys.Add("FSRCBILLTYPEID"); - e.FieldKeys.Add("FSRCBILLNO"); + e.FieldKeys.Add("SRCBILLTYPEID"); // 实体属性名(没有F前缀) + e.FieldKeys.Add("SRCBILLNO"); // 实体属性名(没有F前缀) + e.FieldKeys.Add("SEQ"); + e.FieldKeys.Add("BILLNO"); // 单据编号(主表字段) } - public override void AfterExecuteOperationTransaction(AfterExecuteOperationTransaction e) - { - base.AfterExecuteOperationTransaction(e); - + public override void EndOperationTransaction(EndOperationTransactionArgs e) + { + base.EndOperationTransaction(e); foreach (var dataEntity in e.DataEntitys) { var billObj = dataEntity as DynamicObject; if (billObj == null) continue; - var sdsas = JsonHelper.ToJson(billObj); - Logger.Error("销售增值税专用发票", sdsas, new Exception()); + // 获取单据体 var entrys = billObj["SALESICENTRY"] as DynamicObjectCollection; if (entrys == null || entrys.Count == 0) @@ -45,58 +43,51 @@ namespace Pilot_KD_Parino.AR_SalesVATInvoice.ServicePlugIn foreach (var entry in entrys) { - var entryId = Convert.ToInt64(entry["FENTRYID"]); + // 使用 Id 获取主键值 + var entryId = Convert.ToInt64(entry.GetPrimaryKeyValue()); var fidd = entry["FIDD"]; var fiddValue = fidd == null ? 0 : Convert.ToInt64(fidd); if (fiddValue > 0) { // FIDD > 0 时,判断是否需要回写 - var srcBillNo = entry["FSRCBILLNO"]?.ToString() ?? ""; - Logger.Error("销售增值税专用发票", "56", new Exception()); - // FIDD != 当前行FENTRYID 且 源单编号为空 时才回写 + var srcBillNo = entry["SRCBILLNO"]?.ToString() ?? ""; + + // 判断条件:FIDD != 当前行ID 且 源单编号为空 if (fiddValue != entryId && string.IsNullOrWhiteSpace(srcBillNo)) { - // 查询源单据体信息(主键=FIDD的明细行) - var sql = $@"/*dialect*/ -SELECT FSRCBILLTYPEID, FSRCBILLNO, FSEQ -FROM T_IV_SALESICENTRY -WHERE FENTRYID = {fiddValue}"; - Logger.Error("销售增值税专用发票", sql, new Exception()); - var result = DBServiceHelper.ExecuteDynamicObject(this.Context, sql); - if (result == null || result.Count == 0) - continue; - Logger.Error("销售增值税专用发票", "69", new Exception()); - var srcData = result[0]; - var srcBillTypeId = srcData["FSRCBILLTYPEID"]; - var srcBillNoValue = srcData["FSRCBILLNO"]; + // 从当前单据主表获取单据编号(实体属性名:BILLNO) + var billNo = billObj["BILLNO"]?.ToString() ?? ""; + // 固定源单类型为"销售增值税专用发票" + var srcBillType = "IV_SALESIC"; // 回写当前单据体:源单类型、源单编号 + // 这里使用数据库字段名(带F前缀) var updateSql = $@"/*dialect*/ UPDATE T_IV_SALESICENTRY -SET FSRCBILLTYPEID = '{srcBillTypeId}', - FSRCBILLNO = '{srcBillNoValue}' +SET FSRCBILLTYPEID = '{srcBillType.Replace("'", "''")}', + FSRCBILLNO = '{billNo.Replace("'", "''")}' WHERE FENTRYID = {entryId}"; Logger.Error("销售增值税专用发票", updateSql, new Exception()); - Logger.Error("销售增值税专用发票", "80", new Exception()); + Logger.Error("销售增值税专用发票", "78", new Exception()); DBServiceHelper.Execute(this.Context, updateSql); } } else { - Logger.Error("销售增值税专用发票", "", new Exception()); - // FIDD <= 0 时,把当前行FENTRYID赋值给FIDD,同时把FSEQ赋值给FSEQQ + // FIDD <= 0 时,把当前行FID赋值给FIDD,同时把FSEQ赋值给FSEQQ + var seq = entry["SEQ"]?.ToString() ?? "0"; var updateSql = $@"/*dialect*/ UPDATE T_IV_SALESICENTRY -SET FIDD = FENTRYID, - FSEQQ = FSEQ +SET FIDD = {entryId}, + FSEQQ = '{seq.Replace("'", "''")}' WHERE FENTRYID = {entryId}"; - Logger.Error("销售增值税专用发票", "93", new Exception()); + Logger.Error("销售增值税专用发票", updateSql, new Exception()); + Logger.Error("销售增值税专用发票", "78", new Exception()); DBServiceHelper.Execute(this.Context, updateSql); } } } } } -} - +} \ No newline at end of file diff --git a/Pilot_KD_Parino/Common/CommonHelper.cs b/Pilot_KD_Parino/Common/CommonHelper.cs index 0b13402..62d0b53 100644 --- a/Pilot_KD_Parino/Common/CommonHelper.cs +++ b/Pilot_KD_Parino/Common/CommonHelper.cs @@ -112,59 +112,153 @@ namespace Pilot_KD_Parino.Common } else if (FType == "SX-1" || FType == "SX-2") { - #region 这里开始复制 - // 假设模板中的表格是第一个表格 + #region SX类型:按五大类结构生成(设备层、通讯层、应用管理层、线缆施工费用、技术服务费) + // 存储过程返回的第3个结果集(Tables[2])字段顺序: + // 0=fseq, 1=fname, 2=FSPECIFICATION, 3=F_103(品牌), 4=FLOOR(FQTY), 5=FNAME(单位), + // 6=FTAXPRICE, 7=FALLAMOUNT_LC, 8=FNOTE, 9=FType(F_Projecttype), 10=FALLAMOUNT, 11=FALLAMOUNT2 var table = document.Tables[2]; - //// 清空表格中的所有行(除了表头,如果有的话) - //// 注意:这里假设第一行是表头,不删除 Row previousRowNew = (Row)table.Rows[1]; Row previousRowthreeNew = (Row)table.Rows[2]; Row previousRowfourNew = (Row)table.Rows[3]; - for (int i = 1; i <=3; i++) + for (int i = 1; i <= 3; i++) { table.Rows[i].Remove(); } var datatable2 = data.Tables[2]; - - // 使用LINQ来获取去重后的FType字段 - var DistinctFTypes = datatable2.AsEnumerable() - .Select(row => row.Field("FType")) - .Distinct() - .ToList(); - int Index = DistinctFTypes.Count; - foreach (var item in DistinctFTypes) + + // 定义五大类及其名称(顺序:1-5对应F_Projecttype的值) + List categoryList = new List { "设备层", "通讯层", "应用管理层", "线缆施工费用", "技术服务费" }; + + // 获取系统总价(从第一行数据获取,所有行的FALLAMOUNT值相同) + string systemTotalAmount = "0.00"; + if (datatable2.Rows.Count > 0) { + systemTotalAmount = Convert.ToString(datatable2.Rows[0][10]); // FALLAMOUNT + } + + // 按F_Projecttype分类处理(从5到1倒序插入,确保最终显示顺序为1→5) + for (int categoryIndex = 5; categoryIndex >= 1; categoryIndex--) + { + // 筛选当前类别的数据(FType字段对应F_Projecttype,索引9) + var Rows = datatable2.AsEnumerable() + .Where(t => Convert.ToInt32(t[9]) == categoryIndex) // FType字段(索引9) + .OrderBy(t => Convert.ToInt32(t[0])) // 按fseq排序 + .ToList(); + + string categoryName = categoryList[categoryIndex - 1]; Row previousRow = previousRowNew; var previousRowthree = previousRowthreeNew; var previousRowfour = previousRowfourNew; - //插入组合中具体的数据行 - var Rows = datatable2.AsEnumerable().Where(t => Convert.ToString(t["FType"]) == item).ToList(); - //插入一个组合 - #region - Row newRowfour = table.InsertRow(previousRowfour, 1); - newRowfour.Cells[1].ReplaceText("{9}", Convert.ToString(Rows[0][11])); - int j = 0; - foreach (var Row in Rows) + + // 如果该类别没有数据,创建空行 + if (Rows == null || Rows.Count == 0) { - Row newRowthree = table.InsertRow(previousRowthree, 1+j); + // 1. 插入小计行(显示"小计"和0.00) + Row newRowfour = table.InsertRow(previousRowfour, 1); + SetRowBorder(newRowfour); + newRowfour.Cells[0].ReplaceText("{0}", ""); + newRowfour.Cells[1].ReplaceText("{1}", "小计"); + for (int i = 2; i < 7; i++) + { + if (i < newRowfour.Cells.Count) + { + newRowfour.Cells[i].ReplaceText("{" + i.ToString() + "}", ""); + } + } + if (newRowfour.Cells.Count > 7) + { + newRowfour.Cells[7].ReplaceText("{7}", "0.00"); // 总价列显示0.00 + } + if (newRowfour.Cells.Count > 8) + { + newRowfour.Cells[8].ReplaceText("{8}", ""); + } + + // 2. 插入空明细行(所有占位符清空) + Row newRowthree = table.InsertRow(previousRowthree, 1); + SetRowBorder(newRowthree); for (int i = 0; i < 9; i++) { - newRowthree.Cells[i].ReplaceText("{" + i.ToString() + "}", Convert.ToString(Row[i])); + if (i < newRowthree.Cells.Count) + { + newRowthree.Cells[i].ReplaceText("{" + i.ToString() + "}", ""); + } + } + + // 3. 插入分类标题行 + Row newRow = table.InsertRow(previousRow, 1); + SetRowBorder(newRow); + newRow.Cells[0].ReplaceText("{0}", string.Format("{0}、{1}", ConvertToChineseUppercase(categoryIndex), categoryName)); + for (int i = 1; i < newRow.Cells.Count; i++) + { + if (i < newRow.Cells.Count) + { + newRow.Cells[i].ReplaceText("{" + i.ToString() + "}", ""); + } + } + } + else + { + // 1. 插入小计行(显示"小计"和类别小计金额) + Row newRowfour = table.InsertRow(previousRowfour, 1); + SetRowBorder(newRowfour); + newRowfour.Cells[0].ReplaceText("{0}", ""); + newRowfour.Cells[1].ReplaceText("{1}", "小计"); + for (int i = 2; i < 7; i++) + { + if (i < newRowfour.Cells.Count) + { + newRowfour.Cells[i].ReplaceText("{" + i.ToString() + "}", ""); + } + } + // 小计金额从FALLAMOUNT2获取(索引11),显示在总价列(索引7) + if (newRowfour.Cells.Count > 7) + { + string subtotalAmount = Convert.ToString(Rows[0][11]); // FALLAMOUNT2 + newRowfour.Cells[7].ReplaceText("{7}", subtotalAmount); + } + if (newRowfour.Cells.Count > 8) + { + newRowfour.Cells[8].ReplaceText("{8}", ""); + } + + // 2. 插入明细行(字段映射:索引0-8对应模板占位符{0}-{8}) + int j = 0; + foreach (var Row in Rows) + { + Row newRowthree = table.InsertRow(previousRowthree, 1 + j); + SetRowBorder(newRowthree); + for (int i = 0; i < 9; i++) + { + if (i < newRowthree.Cells.Count) + { + newRowthree.Cells[i].ReplaceText("{" + i.ToString() + "}", Convert.ToString(Row[i])); + } + } + j++; + } + + // 3. 插入分类标题行 + Row newRow = table.InsertRow(previousRow, 1); + SetRowBorder(newRow); + newRow.Cells[0].ReplaceText("{0}", string.Format("{0}、{1}", ConvertToChineseUppercase(categoryIndex), categoryName)); + for (int i = 1; i < newRow.Cells.Count; i++) + { + if (i < newRow.Cells.Count) + { + newRow.Cells[i].ReplaceText("{" + i.ToString() + "}", ""); + } } - document.ReplaceText("{10}", Convert.ToString(Row[10])); - j++; } - Row newRow = table.InsertRow(previousRow, 1); - newRow.Cells[0].ReplaceText("{0}", string.Format("{0}、{1}", ConvertToChineseUppercase(Index), Convert.ToString(item))); - #endregion - Index--; - } + + // 替换系统总价占位符(在文档中全局替换{10}) + document.ReplaceText("{10}", systemTotalAmount); #endregion } else if (!List.Contains(FType) && FType != "HH" && FType != "TH") { - // 假设模板中的表格是第一个表格 + var table = document.Tables[1]; Row previousRow = (Row)table.Rows[1]; //for (int i = table.Rows.Count - 4; i >= 1; i--) // 从最后一行开始删除,避免索引超出范围 @@ -179,7 +273,7 @@ namespace Pilot_KD_Parino.Common foreach (var cell in newRow.Cells) { { - // 注意:如果单元格中有多个段落或更复杂的结构,你可能需要遍历它们并分别复制样式 + Border Border = new Border() { Size = BorderSize.four, Color = Color.Black }; cell.SetBorder(TableCellBorderType.Left, Border); cell.SetBorder(TableCellBorderType.Right, Border); @@ -1520,5 +1614,21 @@ namespace Pilot_KD_Parino.Common CommonHelper.SaveBill(ctx, billView, saveOption, true, out FID, out FBILLNO); return FBILLNO; } + + /// + /// 设置Word表格行的边框样式 + /// + /// 表格行 + private static void SetRowBorder(Row row) + { + foreach (var cell in row.Cells) + { + Border border = new Border() { Size = BorderSize.four, Color = Color.Black }; + cell.SetBorder(TableCellBorderType.Left, border); + cell.SetBorder(TableCellBorderType.Right, border); + cell.SetBorder(TableCellBorderType.Top, border); + cell.SetBorder(TableCellBorderType.Bottom, border); + } + } } } diff --git a/Pilot_KD_Parino/Pilot_KD_Parino.csproj b/Pilot_KD_Parino/Pilot_KD_Parino.csproj index ce960a0..47db624 100644 --- a/Pilot_KD_Parino/Pilot_KD_Parino.csproj +++ b/Pilot_KD_Parino/Pilot_KD_Parino.csproj @@ -322,6 +322,7 @@ +