Procházet zdrojové kódy

优化控制器逻辑并新增 Excel 下载功能

在 `FinancialController.cs` 中简化了 `else` 语句,新增 `GroupAccFee‌ExcelDownload` 方法以处理会计团组费用的 Excel 下载,包含用户权限和团组信息验证。

在 `GroupsController.cs` 中新增 `GroupOrderPreInfoH5URLList` 方法,支持根据用户名称获取团组前期信息的 H5 URL 列表。

在 `Program.cs` 中修改控制器配置,添加自定义的无效模型状态响应处理,提供更详细的错误信息。

在 `ProceedsReceivedDto.cs` 中新增 `GroupAccFee‌ExcelDto` 类,包含团组 ID 和用户 ID 的验证属性。

在 `Fin_ProceedsReceivedView.cs` 中新增 `GroupAccFee‌ExcelView` 类,定义与会计团组费用相关的属性。
Lyyyi před 1 týdnem
rodič
revize
c7b8c3e00c

+ 114 - 4
OASystem/OASystem.Api/Controllers/FinancialController.cs

@@ -1589,10 +1589,7 @@ namespace OASystem.API.Controllers
                     data = ffrData.Data;
 
                 }
-                else
-                {
-                    return Ok(JsonView(false, "请选择正确的端口号!"));
-                }
+                else return Ok(JsonView(false, "请选择正确的端口号!"));
                 return Ok(JsonView(true, "操作成功!", data));
             }
             catch (Exception ex)
@@ -1711,6 +1708,119 @@ namespace OASystem.API.Controllers
             }
         }
 
+        /// <summary>
+        /// 已收款项
+        /// 会计团组费用excel下载
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpPost]
+        [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
+        public async Task<IActionResult> GroupAccFee‌ExcelDownload(GroupAccFee‌ExcelDto dto)
+        {
+            //用户权限验证:只有财务部门的同事才能下载
+            var userInfo = await _sqlSugar.Queryable<Sys_Users>()
+                .LeftJoin<Sys_Department>((x, y) => x.DepId == y.Id)
+                .Where((x, y) => x.Id == dto.UserId && x.IsDel == 0 && y.DepName.Contains("财务"))
+                .FirstAsync();
+            if (userInfo == null) return Ok(JsonView(false, "只有财务部同事可下载!"));
+
+            //团组信息验证
+            var groupInfo = await _sqlSugar.Queryable<Grp_DelegationInfo>()
+                .FirstAsync(x => x.Id == dto.GroupId && x.IsDel == 0);
+            if (groupInfo == null) return Ok(JsonView(false, "团组信息不存在或已删除,不可下载!"));
+
+            //已收款项信息验证
+            var proceedInfos = await _sqlSugar.Queryable<Fin_ProceedsReceived>()
+                .Where(x => x.Diid == dto.GroupId && x.IsDel == 0)
+                .Select(x => new GroupAccFee‌ExcelView() {
+                    OrgName‌ = x.Client,
+                    VisitorNum‌ = 1, //假设每条记录代表一个访客
+                    ActualAR = 0.00M,
+                    PaidDate‌ = x.SectionTime,
+                    PaidAmount‌ = x.Price,
+                    Remark = x.Remark,
+                })
+                .ToListAsync();
+            if (!proceedInfos.Any()) return Ok(JsonView(false, "已收款项信息不存在或已删除,不可下载!"));
+
+            var costInfo = await _sqlSugar.Queryable<Grp_EnterExitCost>()
+                .Where(x => x.DiId == dto.GroupId && x.IsDel == 0)
+                .FirstAsync();
+
+            var rateInfos = CommonFun.GetCurrencyChinaToList(costInfo.CurrencyRemark);
+
+            var hotelCostInfos = await _sqlSugar.Queryable<Grp_DayAndCost>()
+               .LeftJoin<Sys_SetData>((x, y) => x.Currency == y.Id)
+               .Where((x, y) => x.DiId == dto.GroupId && x.Type == 1 && x.IsDel == 0)
+               .Select((x, y) => new { x.Place, x.Cost, x.Currency, y.Name,CurrencyName = y.Remark, Rate = x.SubTotal / x.Cost, x.SubTotal })
+               .ToListAsync();
+
+            decimal visaFee = costInfo?.Visa ?? 0.00M, //签证费
+                    IntercityFare = costInfo?.CityTranffic ?? 0.00M, //城市区间交通费
+                    hotelFee = hotelCostInfos.Sum(x => x.Cost), //住宿费
+                    hotelCNYEquivalent = hotelCostInfos.Sum(x => x.SubTotal), //住宿费CNY折算价
+                    hotelRate = rateInfos.FirstOrDefault(x => x.CurrencyCode.Equals(hotelCostInfos.FirstOrDefault().Name))?.Rate ?? 0.00M; //住宿费汇率
+            string hotelCurrency = hotelCostInfos.FirstOrDefault()?.CurrencyName ?? "-"; //住宿费币种
+
+            var costInfosNew = new List<GroupAccFee‌ExcelView>() {
+                new (){ CostName = "酒店",CostAmt = hotelFee,CostCurrency = hotelCurrency, CostRate = hotelRate, CNYEquivalent = hotelCNYEquivalent},
+                new (){ CostName = "市区间交通",CostAmt = IntercityFare,CostCurrency = "人民币" },
+                new (){ CostName = "签证",CostAmt = visaFee,CostCurrency = "人民币" },
+            };
+
+            if (proceedInfos == null || proceedInfos.Count < 1) proceedInfos = costInfosNew;
+            int replaceCount = Math.Min(proceedInfos.Count, costInfosNew.Count);
+            // 替换元素
+            for (int i = 0; i < replaceCount; i++)
+            {
+                var newInfo = costInfosNew[i];
+                proceedInfos[i].CostName = newInfo.CostName;
+
+                if (newInfo.CostAmt != null && newInfo.CostAmt > 0.00M) proceedInfos[i].CostAmt = newInfo.CostAmt;
+                if (newInfo.CostRate != null && newInfo.CostRate > 0.00M) proceedInfos[i].CostRate = newInfo.CostRate;
+                if (newInfo.CNYEquivalent != null && newInfo.CNYEquivalent > 0.00M) proceedInfos[i].CNYEquivalent = newInfo.CNYEquivalent;
+
+                proceedInfos[i].CostCurrency = newInfo.CostCurrency;
+            }
+
+            // 添加剩余元素
+            if (costInfosNew.Count > proceedInfos.Count) proceedInfos.AddRange(costInfosNew.Skip(proceedInfos.Count));
+
+            int index = 1;
+            proceedInfos.ForEach( x=> {
+                x.Index = index;
+                index++;
+            });
+
+            string url = string.Empty;
+            #region 生成Excel文件
+
+            var designer = new WorkbookDesigner
+            {
+                Workbook = new Workbook(AppSettingsHelper.Get("ExcelBasePath") + "Template/‌GroupAccFee‌Temp.xlsx")
+            };
+            designer.SetDataSource("DataView", proceedInfos);
+
+            //根据数据源处理生成报表内容
+            designer.Process();
+
+            //设置sum函数
+            int cellIndex = proceedInfos.Count + 3;
+            int cellFormulaIndex = cellIndex - 1;
+            var calcFormula‌ = $"=SUM(F3:F{cellFormulaIndex})";
+            designer.Workbook.Worksheets[0].Cells[$"F{cellIndex}"].Formula = calcFormula‌;
+
+            //计算sum函数
+            designer.Workbook.Worksheets[0].CalculateFormula(new CalculationOptions() { IgnoreError = true }, true);
+
+            string fileName = $"AmountReceived/{groupInfo.TeamName}_会计团组费用{Guid.NewGuid().ToString()}.xlsx";
+            designer.Workbook.Save(AppSettingsHelper.Get("ExcelBasePath") + fileName);
+            url = AppSettingsHelper.Get("ExcelBaseUrl") + AppSettingsHelper.Get("ExcelFtpPath") + fileName;
+            #endregion
+            return Ok(JsonView(true,"操作成功!",url));
+        }
+
         #endregion
 
         #region 收款退还与其他款项 --> 收款退还

+ 22 - 0
OASystem/OASystem.Api/Controllers/GroupsController.cs

@@ -386,6 +386,28 @@ namespace OASystem.API.Controllers
         #endregion
 
         #region 团组前期信息
+        /// <summary>
+        /// 团组前期信息H5-URL(员工对应地址)
+        /// </summary>
+        /// <param name="name">用户名称</param>
+        /// <returns></returns>
+        [HttpGet]
+        [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
+        public async Task<IActionResult> GroupOrderPreInfoH5URLList([FromQuery] string name)
+        {
+            var userURLs = await _sqlSugar.Queryable<Sys_Users>()
+                .Where(x => x.IsDel == 0)
+                .WhereIF(!string.IsNullOrEmpty(name), x => x.CnName.Contains(name))
+                .OrderBy(x => x.Id)
+                .Select(x => new
+                {
+                    name = x.CnName,
+                    url = $"http://oa.pan-american-intl.com:4399/#/MarketplacePick?userid={x.Id}",
+                })
+                .ToListAsync();
+
+            return Ok(JsonView(true, "操作成功!", userURLs, userURLs.Count()));
+        }
 
         /// <summary>
         ///  团组前期信息 List

+ 24 - 0
OASystem/OASystem.Api/Program.cs

@@ -36,6 +36,30 @@ builder.Services.AddSingleton(new AppSettingsHelper(_config));
 //设置请求参数可不填
 builder.Services.AddControllers(options => options.SuppressImplicitRequiredAttributeForNonNullableReferenceTypes = true);
 
+//设置请求参数错误默认返回格式
+builder.Services.AddControllers()
+    .ConfigureApiBehaviorOptions(options =>
+    {
+        options.InvalidModelStateResponseFactory = context =>
+        {
+            var errors = context.ModelState
+                .Where(e => e.Value.Errors.Count > 0)
+                .ToDictionary(
+                    kvp => kvp.Key,
+                    kvp => kvp.Value.Errors.Select(e => e.ErrorMessage).ToArray()
+                );
+
+            var result = new JsonView
+            {
+                Code = 400,
+                Msg = errors.FirstOrDefault().Value.FirstOrDefault() ?? "",
+                Data = errors
+            };
+
+            return new BadRequestObjectResult(result);
+        };
+    });
+
 // Add services to the container.
 builder.Services.AddControllersWithViews();
 builder.Services.AddControllers()

+ 16 - 0
OASystem/OASystem.Domain/Dtos/Financial/ProceedsReceivedDto.cs

@@ -1,5 +1,6 @@
 using System;
 using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
@@ -252,5 +253,20 @@ namespace OASystem.Domain.Dtos.Financial
 
         public int Id { get; set; }
     }
+
+    public class GroupAccFee‌ExcelDto
+    {
+        /// <summary>
+        /// 团组Id
+        /// </summary>
+        [Range(1, int.MaxValue, ErrorMessage = "请检查团组Id是否正确!")]
+        public int GroupId { get; set; } = 1;
+
+        /// <summary>
+        /// 用户Id
+        /// </summary>
+        [Range(1, int.MaxValue, ErrorMessage = "请检查用户Id是否正确!")]
+        public int UserId { get; set; } = 1;
+    }
     #endregion
 }

+ 66 - 0
OASystem/OASystem.Domain/ViewModels/Financial/Fin_ProceedsReceivedView.cs

@@ -125,4 +125,70 @@ namespace OASystem.Domain.ViewModels.Financial
         /// </summary>
         public string? Remark { get; set; }
     }
+
+    /// <summary>
+    /// 会计团组费用excel View
+    /// </summary>
+    public class GroupAccFee‌ExcelView
+    {
+        /// <summary>
+        /// 序号
+        /// </summary>
+        public int Index { get; set; }
+
+        /// <summary>
+        /// 单位名称
+        /// </summary>
+        public string OrgName‌ { get; set; }
+
+        /// <summary>
+        /// 出访人数
+        /// </summary>
+        public int VisitorNum‌ { get; set; } 
+
+        /// <summary>
+        /// 实际应收金额
+        /// </summary>
+        public decimal? ActualAR { get; set; } = null;
+
+        /// <summary>
+        /// 已收款日期
+        /// </summary>
+        public string PaidDate‌ { get; set; }
+
+        /// <summary>
+        /// 已收款金额
+        /// </summary>
+        public decimal? PaidAmount‌ { get; set; }
+
+        /// <summary>
+        /// 成本费用-名称
+        /// </summary>
+        public string CostName { get; set; }
+
+        /// <summary>
+        /// 成本费用-金额
+        /// </summary>
+        public decimal? CostAmt‌ { get; set; } = null;
+
+        /// <summary>
+        /// 成本费用-币种
+        /// </summary>
+        public string CostCurrency‌ { get; set; }
+
+        /// <summary>
+        /// 成本费用-汇率
+        /// </summary>
+        public decimal? CostRate‌ { get; set; } = null;
+
+        /// <summary>
+        /// 成本费用-折算人民币
+        /// </summary>
+        public decimal? CNYEquivalent { get; set; } = null;
+
+        /// <summary>
+        /// 备注
+        /// </summary>
+        public string Remark { get; set; }
+    }
 }