Forráskód Böngészése

Merge branch 'develop' of http://132.232.92.186:3000/XinXiBu/OA2023 into develop

yuanrf 3 hónapja%!(EXTRA string=óta)
szülő
commit
c5232e8ab7
23 módosított fájl, 1711 hozzáadás és 639 törlés
  1. 6 0
      OASystem/.cr/personal/Editor/IntelliRush.xml
  2. 6 0
      OASystem/.cr/personal/Editor/Painting/Member Icons.xml
  3. 6 0
      OASystem/.cr/personal/Editor/Painting/Structural Highlighting.xml
  4. 6 0
      OASystem/.cr/personal/Editor/Spell checker.xml
  5. 6 0
      OASystem/.cr/personal/FavoritesList/List.xml
  6. 6 0
      OASystem/.cr/personal/Navigation/Code Places.xml
  7. 6 0
      OASystem/.cr/personal/Unit Testing/Continuous Testing.xml
  8. 79 52
      OASystem/OASystem.Api/Controllers/FinancialController.cs
  9. 151 96
      OASystem/OASystem.Api/Controllers/GroupsController.cs
  10. 314 283
      OASystem/OASystem.Api/Controllers/PersonnelModuleController.cs
  11. 7 0
      OASystem/OASystem.Api/Controllers/ResourceController.cs
  12. 272 0
      OASystem/OASystem.Api/Controllers/SystemController.cs
  13. 159 2
      OASystem/OASystem.Api/OAMethodLib/QiYeWeChatAPI/AppNotice/Library.cs
  14. 7 0
      OASystem/OASystem.Domain/ViewModels/Financial/Fin_ForeignReceivablesView.cs
  15. 1 0
      OASystem/OASystem.Domain/ViewModels/Groups/OrderPreInfoView.cs
  16. 23 0
      OASystem/OASystem.Domain/ViewModels/PersonnelModule/GoodsInfoView.cs
  17. 2 2
      OASystem/OASystem.Infrastructure/Repositories/Groups/AirTicketResRepository.cs
  18. 225 45
      OASystem/OASystem.Infrastructure/Repositories/Groups/FeeAuditRepository.cs
  19. 9 0
      OASystem/OASystem.Infrastructure/Repositories/Groups/GroupOrderPreInfoRepository.cs
  20. 282 113
      OASystem/OASystem.Infrastructure/Repositories/PersonnelModule/GoodsRepository.cs
  21. 77 45
      OASystem/OASystem.Infrastructure/Repositories/Resource/OfficialActivitiesRepository.cs
  22. 24 0
      OASystem/OASystem.Infrastructure/Repositories/System/ApprovalProcessRepository.cs
  23. 37 1
      OASystem/OASystem.Infrastructure/Tools/CommonFun.cs

+ 6 - 0
OASystem/.cr/personal/Editor/IntelliRush.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Root Type="DevExpress.IntelliRush.Options.IntelliRushOptions">
+  <Options Language="Neutral">
+    <DisabledLanguages />
+  </Options>
+</Root>

+ 6 - 0
OASystem/.cr/personal/Editor/Painting/Member Icons.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Root Type="DevExpress.CodeRush.VisualizePlugins.MemberIcons.Options.MemberIconOptions">
+  <Options Language="Neutral">
+    <Enabled>False</Enabled>
+  </Options>
+</Root>

+ 6 - 0
OASystem/.cr/personal/Editor/Painting/Structural Highlighting.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Root Type="DevExpress.CodeRush.VisualizePlugins.StructuralHighlighting.Options.StructuralHighlightingOptions">
+  <Options Language="Neutral">
+    <Enabled>False</Enabled>
+  </Options>
+</Root>

+ 6 - 0
OASystem/.cr/personal/Editor/Spell checker.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Root Type="DevExpress.CodeRush.VSFeatures.SpellChecker.Options.SpellCheckerOptions">
+  <Options Language="Neutral">
+    <Enabled>False</Enabled>
+  </Options>
+</Root>

+ 6 - 0
OASystem/.cr/personal/FavoritesList/List.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Root Type="DevExpress.CodeRush.Foundation.CodePlaces.Options.FavoritesListContainer">
+  <Options Language="Neutral">
+    <Groups />
+  </Options>
+</Root>

+ 6 - 0
OASystem/.cr/personal/Navigation/Code Places.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Root Type="DevExpress.CodeRush.Foundation.CodePlaces.Options.CodePlacesOptions">
+  <Options Language="Neutral">
+    <AutoHide>True</AutoHide>
+  </Options>
+</Root>

+ 6 - 0
OASystem/.cr/personal/Unit Testing/Continuous Testing.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Root Type="DevExpress.CodeRush.ContinuousTesting.Options.ContinuousTestingOptions">
+  <Options Language="Neutral">
+    <SplitterOrientation>Horizontal</SplitterOrientation>
+  </Options>
+</Root>

+ 79 - 52
OASystem/OASystem.Api/Controllers/FinancialController.cs

@@ -1874,60 +1874,89 @@ namespace OASystem.API.Controllers
         public async Task<IActionResult> PostSyntheticalReceivableByDateRange(PostSyntheticalReceivableByDateRangeDto dto)
         {
 
-            string sqlWhere = " Where di.IsDel=0 ";
+            #region 老版查询
+            //string sqlWhere = " Where di.IsDel=0 ";
 
-            #region 验证
-            if (string.IsNullOrEmpty(dto.beginDt) && string.IsNullOrEmpty(dto.endDt))
-            {
-                return Ok(JsonView(false, "日期参数至少填写一个!"));
-            }
+            //#region 验证
+            //if (string.IsNullOrEmpty(dto.beginDt) && string.IsNullOrEmpty(dto.endDt))
+            //{
+            //    return Ok(JsonView(false, "日期参数至少填写一个!"));
+            //}
 
-            if (!string.IsNullOrEmpty(dto.beginDt))
-            {
-                if (Regex.Match(dto.beginDt, @"^\d{4}-\d{2}-\d{2}$").Value.Length < 1)
-                {
-                    return Ok(JsonView(false, "日期参数格式错误,应为yyyy-MM-dd!"));
-                }
-                else
-                {
-                    sqlWhere += string.Format(@" And di.VisitDate >= '{0} 00:00:00' ", dto.beginDt);
-                }
-            }
+            //if (!string.IsNullOrEmpty(dto.beginDt))
+            //{
+            //    if (Regex.Match(dto.beginDt, @"^\d{4}-\d{2}-\d{2}$").Value.Length < 1)
+            //    {
+            //        return Ok(JsonView(false, "日期参数格式错误,应为yyyy-MM-dd!"));
+            //    }
+            //    else
+            //    {
+            //        sqlWhere += string.Format(@" And di.VisitDate >= '{0} 00:00:00' ", dto.beginDt);
+            //    }
+            //}
 
-            if (!string.IsNullOrEmpty(dto.endDt))
-            {
-                if (Regex.Match(dto.endDt, @"^\d{4}-\d{2}-\d{2}$").Value.Length < 1)
-                {
-                    return Ok(JsonView(false, "日期参数格式错误,应为yyyy-MM-dd!"));
-                }
-                else
-                {
-                    sqlWhere += string.Format(@" And di.VisitDate <= '{0} 23:59:59' ", dto.endDt);
-                }
-            }
+            //if (!string.IsNullOrEmpty(dto.endDt))
+            //{
+            //    if (Regex.Match(dto.endDt, @"^\d{4}-\d{2}-\d{2}$").Value.Length < 1)
+            //    {
+            //        return Ok(JsonView(false, "日期参数格式错误,应为yyyy-MM-dd!"));
+            //    }
+            //    else
+            //    {
+            //        sqlWhere += string.Format(@" And di.VisitDate <= '{0} 23:59:59' ", dto.endDt);
+            //    }
+            //}
 
-            if (!string.IsNullOrEmpty(dto.groupName))
-            {
-                sqlWhere += string.Format(@" And di.TeamName Like '%{0}%' ", dto.groupName);
-            }
+            //if (!string.IsNullOrEmpty(dto.groupName))
+            //{
+            //    sqlWhere += string.Format(@" And di.TeamName Like '%{0}%' ", dto.groupName);
+            //}
 
-            #endregion
+            //#endregion
 
-            //已收款项 判断如果是市场部的人员进来的话 只显示自己的 其他的都显示全部的
-            string userSqlWhere = "";
-            var userInfos = await _sqlSugar.Queryable<Sys_Users>()
-                                           .InnerJoin<Sys_Department>((u, d) => u.DepId == d.Id)
-                                           .Where((u, d) => u.IsDel == 0 && d.DepName.Contains("市场部") && u.Id == dto.CurrUserId)
-                                           .ToListAsync();
+            ////已收款项 判断如果是市场部的人员进来的话 只显示自己的 其他的都显示全部的
+            //string userSqlWhere = "";
+            //var userInfos = await _sqlSugar.Queryable<Sys_Users>()
+            //                               .InnerJoin<Sys_Department>((u, d) => u.DepId == d.Id)
+            //                               .Where((u, d) => u.IsDel == 0 && d.DepName.Contains("市场部") && u.Id == dto.CurrUserId)
+            //                               .ToListAsync();
+
+            //if (userInfos.Count > 0) userSqlWhere = string.Format(@$" And JietuanOperator={dto.CurrUserId} ");
 
 
-            if (userInfos.Count > 0) userSqlWhere = string.Format(@$" And JietuanOperator={dto.CurrUserId} ");
+            ////排序倒序
+            //string sql = string.Format(@$"select distinct fr.diid,di.TeamName,di.ClientUnit,di.VisitDate,di.CreateTime from Fin_ForeignReceivables fr join Grp_DelegationInfo di on fr.DIID = di.id {sqlWhere}  {userSqlWhere}  Order By di.VisitDate Desc");
 
+            //var list_rst = _sqlSugar.SqlQueryable<PostSyntheticalReceivableByDateRangeView>(sql).ToList();
+            #endregion
 
-            //排序倒序
-            string sql = string.Format(@$"select distinct fr.diid,di.TeamName,di.ClientUnit,di.VisitDate,di.CreateTime from Fin_ForeignReceivables fr join Grp_DelegationInfo di on fr.DIID = di.id {sqlWhere}  {userSqlWhere}  Order By di.VisitDate Desc");
+            //日期验证
+            var startTimeFlag = DateTime.TryParse(dto.beginDt, out DateTime begintime);
+            var endTimeFlag = DateTime.TryParse(dto.endDt, out DateTime endtime);
+            if (!startTimeFlag || !endTimeFlag) return Ok(JsonView(false, "请输入正确的开始、结束时间!"));
 
-            var list_rst = _sqlSugar.SqlQueryable<PostSyntheticalReceivableByDateRangeView>(sql).ToList();
+            string groupName = dto.groupName;
+            int currUserId = dto.CurrUserId;
+
+            //已收款项 判断如果是市场部的人员进来的话 只显示自己的 其他的都显示全部的
+            var marketStaffFlag = await _sqlSugar.Queryable<Sys_Users>()
+                .InnerJoin<Sys_Department>((u, d) => u.DepId == d.Id)
+                .Where((u, d) => u.IsDel == 0 && d.DepName.Contains("市场部") && u.Id == dto.CurrUserId)
+                .AnyAsync();
+
+            var list_rst = await _sqlSugar.Queryable<Grp_DelegationInfo>()
+                .Where(x => x.IsDel == 0)
+                .WhereIF(startTimeFlag && endTimeFlag, x => x.VisitDate >= begintime && x.VisitDate <= endtime)
+                .WhereIF(!string.IsNullOrEmpty(groupName), x=> x.TeamName.Contains(groupName))
+                .WhereIF(marketStaffFlag, x => x.JietuanOperator == currUserId)
+                .OrderBy(x => x.VisitDate)
+                .Select(x => new PostSyntheticalReceivableByDateRangeView() { 
+                    diid = x.Id,
+                    teamName = x.TeamName,
+                    clientUnit = x.ClientUnit,
+                    visitDate = x.VisitDate.ToString("yyyy-MM-dd")
+                })
+                .ToListAsync();
 
             var setData = _sqlSugar.Queryable<Sys_SetData>().Where(it => it.IsDel == 0).ToList();
 
@@ -1935,19 +1964,11 @@ namespace OASystem.API.Controllers
             decimal sumAll_pr = 0M; //已收
             decimal sumAll_balance = 0M; //尾款
             var result = new PostSyntheticalReceivableByDateRangeResultView();
-            if (list_rst.Count > 0)
+            if (list_rst.Any())
             {
                 int rowNumber = 1;
                 foreach (var item_rst in list_rst)
                 {
-                    DateTime dtTemp;
-                    bool b = DateTime.TryParse(item_rst.visitDate, out dtTemp);
-                    if (b)
-                    {
-                        item_rst.visitDate = dtTemp.ToString("yyyy-MM-dd");
-                    }
-
-
                     item_rst.No = rowNumber;
                     rowNumber++;
 
@@ -2063,6 +2084,12 @@ namespace OASystem.API.Controllers
                         }
                     }
 
+                    if (feeDatas.Count < 1)
+                    {
+                        feeDatas.Add(new ClientFeeInfoView() { });
+
+                    }
+
 
                     item_rst.feeItem = feeDatas;
                     #endregion

+ 151 - 96
OASystem/OASystem.Api/Controllers/GroupsController.cs

@@ -1,20 +1,10 @@
 using Aspose.Cells;
-using Aspose.Cells.Drawing;
 using Aspose.Words;
 using Aspose.Words.Drawing;
 using Aspose.Words.Tables;
 using DiffMatchPatch;
-using EyeSoft.Runtime.InteropServices;
-using Google.Protobuf.WellKnownTypes;
-using Microsoft.AspNetCore.Mvc.RazorPages;
 using Microsoft.AspNetCore.SignalR;
-using Microsoft.EntityFrameworkCore.Metadata.Internal;
-using Microsoft.IdentityModel.Tokens;
-using Microsoft.VisualBasic;
-using MySqlX.XDevAPI.Relational;
-using NetTaste;
 using NPOI.HSSF.UserModel;
-using NPOI.SS.Formula.Functions;
 using NPOI.SS.UserModel;
 using NPOI.SS.Util;
 using NPOI.XSSF.UserModel;
@@ -38,32 +28,18 @@ using OASystem.Domain.Entities.Financial;
 using OASystem.Domain.Entities.Groups;
 using OASystem.Domain.ViewModels.Financial;
 using OASystem.Domain.ViewModels.Groups;
-using OASystem.Domain.ViewModels.JuHeExchangeRate;
 using OASystem.Domain.ViewModels.OCR;
-using OASystem.Domain.ViewModels.QiYeWeChat;
-using OASystem.Domain.ViewModels.Statistics;
 using OASystem.Infrastructure.Repositories.CRM;
 using OASystem.Infrastructure.Repositories.Financial;
 using OASystem.Infrastructure.Repositories.Groups;
-using OASystem.Infrastructure.Tools;
-using OASystem.RedisRepository;
-using Org.BouncyCastle.Crypto;
-using Org.BouncyCastle.Utilities;
 using Quartz.Util;
 using SqlSugar.Extensions;
 using System.Collections;
-using System.Collections.Generic;
 using System.Data;
 using System.Diagnostics;
-using System.Drawing.Printing;
 using System.Globalization;
-using System.IO;
 using System.IO.Compression;
-using System.Reflection;
-using System.Text.Json;
 using System.Web;
-using System.Xml.Linq;
-using TencentCloud.Ocr.V20181119.Models;
 using static OASystem.API.OAMethodLib.JWTHelper;
 using static OASystem.Infrastructure.Repositories.Groups.AirTicketResRepository;
 using Bookmark = Aspose.Words.Bookmark;
@@ -432,7 +408,7 @@ namespace OASystem.API.Controllers
                 {
                     Id = opi.Id,
                     Name = opi.Name,
-                    UnitName = SqlFunc.Subqueryable<Grp_OrderPreItem>().Where(x => x.ParentId == opi.Id && nameTempIds.Contains( x.FormTempId)).Select(x => x.Value),
+                    UnitName = SqlFunc.Subqueryable<Grp_OrderPreItem>().Where(x => x.ParentId == opi.Id && nameTempIds.Contains(x.FormTempId)).Select(x => x.Value),
                     VisitCountryVal = SqlFunc.Subqueryable<Grp_OrderPreItem>().Where(x => x.ParentId == opi.Id && countryTempIds.Contains(x.FormTempId)).Select(x => x.Value),
                     VisitDays = SqlFunc.Subqueryable<Grp_OrderPreItem>().Where(x => x.ParentId == opi.Id && daysTempIds.Contains(x.FormTempId)).Select(x => x.Value),
                     VisiPpNum = SqlFunc.Subqueryable<Grp_OrderPreItem>().Where(x => x.ParentId == opi.Id && ppNumTempIds.Contains(x.FormTempId)).Select(x => x.Value),
@@ -538,8 +514,8 @@ namespace OASystem.API.Controllers
         [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
         public async Task<IActionResult> CityByCountry(
             string countryLabel,
-            [FromQuery] int pageIndex, 
-            [FromQuery] int pageSize, 
+            [FromQuery] int pageIndex,
+            [FromQuery] int pageSize,
             [FromQuery] string search)
         {
             countryLabel = HttpUtility.UrlDecode(countryLabel);
@@ -595,7 +571,7 @@ namespace OASystem.API.Controllers
         /// <returns></returns>
         [HttpGet("{Id}/{TempId}")]
         [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
-        public async Task<IActionResult> GroupOrderPreInfo([FromRoute] GroupOrderPreInfoDto dto,int portType=1)
+        public async Task<IActionResult> GroupOrderPreInfo([FromRoute] GroupOrderPreInfoDto dto, int portType = 1)
         {
             return Ok(await _grpOrderPreInfoRep.InfoAsync(dto.Id, dto.TempId));
         }
@@ -1093,10 +1069,10 @@ namespace OASystem.API.Controllers
             di.VisitEndDate = endTime;
 
             var count = _sqlSugar.Updateable(di)
-                .UpdateColumns(x => new { x.VisitDate, x.VisitPNumber, x.VisitDays , x.VisitStartDate, x.VisitEndDate })
+                .UpdateColumns(x => new { x.VisitDate, x.VisitPNumber, x.VisitDays, x.VisitStartDate, x.VisitEndDate })
                 .ExecuteCommand();
 
-            return Ok( count > 0 ? JsonView(true, "操作成功") : jw);
+            return Ok(count > 0 ? JsonView(true, "操作成功") : jw);
         }
 
         /// <summary>
@@ -1698,11 +1674,67 @@ namespace OASystem.API.Controllers
         {
             var diId = dto.Id;
             if (diId < 1) return Ok(JsonView(false, MsgTips.Id));
-            #region 删除 验证 (费用录入、出入境费用、收款账单)
-            //var feeCount = _sqlSugar.Queryable<Grp_CreditCardPayment>().Where(x => x.IsDel == 0 && x.DIId == diId).Count();
-            //var eccCount = _sqlSugar.Queryable<Grp_EnterExitCost>().Where(x => x.IsDel == 0 && x.DiId == diId).Count();
-            //var frCount = _sqlSugar.Queryable<Fin_ForeignReceivables>().Where(x => x.IsDel == 0 && x.Diid == diId).Count();
-            //if (feeCount > 0 || feeCount > 0 || feeCount > 0) return Ok(JsonView(false, "该团组存在费用不可删除!"));
+            #region 删除 验证
+
+            /*
+             * 1、收款账单数据:0 条
+             * 2、收款退还数据:0 条
+             * 3、机票费用数据:0 条
+             * 4、签证费用数据:0 条
+             * 5、保险费用数据:0 条
+             * 6、酒店费用数据:0 条
+             * 7、公务出访数据:1 条
+             * 8、邀请公务活动费用数据:1 条
+             * 9、OP费用数据:5 条
+             * 10、其他费用数据:0 条
+             * 11、团组日付报销费用数据:0 条
+             * 
+             * 温馨提示:该团组已产生费用,不允许删除;如需删除,请先删除对应版块费用,谢谢!
+             */
+
+            //收款账单
+            int frCount = _sqlSugar.Queryable<Fin_ForeignReceivables>().Where(x => x.IsDel == 0 && x.Diid == diId).Count();
+            //收款退还
+            int fraomCount = _sqlSugar.Queryable<Fin_PaymentRefundAndOtherMoney>().Where(x => x.IsDel == 0 && x.DiId == diId).Count();
+            //机票费用
+            int arCount = _sqlSugar.Queryable<Grp_AirTicketReservations>().Where(x => x.IsDel == 0 && x.DIId == diId).Count();
+            //签证费用
+            int viCount = _sqlSugar.Queryable<Grp_VisaInfo>().Where(x => x.IsDel == 0 && x.DIId == diId).Count();
+            //保险费用
+            int cCount = _sqlSugar.Queryable<Grp_Customers>().Where(x => x.IsDel == 0 && x.DiId == diId).Count();
+            //酒店费用
+            int hrCount = _sqlSugar.Queryable<Grp_HotelReservations>().Where(x => x.IsDel == 0 && x.DiId == diId).Count();
+            //公务出访
+            int oaCount = _sqlSugar.Queryable<Res_OfficialActivities>().Where(x => x.IsDel == 0 && x.DiId == diId).Count();
+            //邀请公务活动费用
+            int ioaCount = _sqlSugar.Queryable<Grp_InvitationOfficialActivities>().Where(x => x.IsDel == 0 && x.DiId == diId).Count();
+            //OP费用
+            int ctggrCount = _sqlSugar.Queryable<Grp_CarTouristGuideGroundReservations>().Where(x => x.IsDel == 0 && x.DiId == diId).Count();
+            //其他费用
+            int dpCount = _sqlSugar.Queryable<Grp_DecreasePayments>().Where(x => x.IsDel == 0 && x.DiId == diId).Count();
+            //团组日付报销费用
+            int dfpCount = _sqlSugar.Queryable<Fin_DailyFeePayment>().Where(x => x.IsDel == 0 && x.GroupId == diId).Count();
+
+            var feeCount = frCount + fraomCount + arCount + viCount + cCount + hrCount + oaCount + ioaCount + ctggrCount + dpCount + dfpCount;
+            if (feeCount > 0)
+            {
+                var delMsgTips = new StringBuilder();
+                delMsgTips.AppendLine($"1、收款账单数据:{frCount} 条");
+                delMsgTips.AppendLine($"2、收款退换数据:{fraomCount} 条");
+                delMsgTips.AppendLine($"3、机票费用数据:{arCount} 条");
+                delMsgTips.AppendLine($"4、签证费用数据:{viCount} 条");
+                delMsgTips.AppendLine($"5、保险费用数据:{cCount} 条");
+                delMsgTips.AppendLine($"6、酒店费用数据:{hrCount} 条");
+                delMsgTips.AppendLine($"7、公务出访数据:{oaCount} 条");
+                delMsgTips.AppendLine($"8、邀请公务活动费用数据:{ioaCount} 条");
+                delMsgTips.AppendLine($"9、OP费用数据:{ctggrCount} 条");
+                delMsgTips.AppendLine($"10、其他费用数据:{dpCount} 条");
+                delMsgTips.AppendLine($"11、团组日付报销费用数据:{dfpCount} 条");
+                delMsgTips.AppendLine($"");
+                delMsgTips.AppendLine($"温馨提示:该团组已产生费用,不允许删除;如需删除,请先删除对应版块费用,谢谢!");
+
+                return Ok(JsonView(false, delMsgTips.ToString()));
+            }
 
             #endregion
 
@@ -2102,7 +2134,7 @@ FROM
 
 
             var blackCodeList = await _sqlSugar.Queryable<Air_TicketBlackCode>()
-                                                .Where(x=>x.DiId == dto.GroupId && x.IsDel == 0)
+                                                .Where(x => x.DiId == dto.GroupId && x.IsDel == 0)
                                                 .ToListAsync();
 
             if (!blackCodeList.Any())
@@ -2172,14 +2204,14 @@ FROM
             var groupClints = await _sqlSugar.Queryable<Grp_TourClientList>()
                 .LeftJoin<Sys_SetData>((x, s) => s.Id == x.ShippingSpaceTypeId && s.IsDel == 0)
                 .LeftJoin<Crm_DeleClient>((x, s, dc) => x.ClientId == dc.Id && dc.IsDel == 0)
-                .LeftJoin<Crm_CustomerCompany>((x, s, dc,cc) => dc.CrmCompanyId == cc.Id && cc.IsDel == 0)
+                .LeftJoin<Crm_CustomerCompany>((x, s, dc, cc) => dc.CrmCompanyId == cc.Id && cc.IsDel == 0)
                 .Where((x, s, dc, cc) => x.DiId == dto.GroupId && x.IsDel == 0)
                 .Select((x, s, dc, cc) => new groupClints
                 {
-                    Id =x.Id,
-                    Name =s.Name,
-                    IsAccompany =x.IsAccompany,
-                    CompanyFullName =cc.CompanyFullName
+                    Id = x.Id,
+                    Name = s.Name,
+                    IsAccompany = x.IsAccompany,
+                    CompanyFullName = cc.CompanyFullName
                 })
                 .ToListAsync();
 
@@ -2208,14 +2240,14 @@ FROM
             }
 
             Dictionary<string, string> bookMarkDic = new Dictionary<string, string>();
-            bookMarkDic.Add("ClientUnit",di.ClientUnit);
+            bookMarkDic.Add("ClientUnit", di.ClientUnit);
             bookMarkDic.Add("VisitCountry", di.VisitCountry);
             bookMarkDic.Add("VisitDate", di.VisitDate.ToString("yyyy年MM月dd日"));
             bookMarkDic.Add("VisitPNumber", di.VisitPNumber.ToString());
             bookMarkDic.Add("CityPath", cityPath);
             bookMarkDic.Add("StartCity", startCity);
             bookMarkDic.Add("EndCity", endCity);
-            bookMarkDic.Add("StayDays", $"{di.VisitDays}天{di.VisitDays -1}晚");
+            bookMarkDic.Add("StayDays", $"{di.VisitDays}天{di.VisitDays - 1}晚");
 
             Document doc = null;
             var percentage = 0.8M;
@@ -2250,7 +2282,7 @@ FROM
                         var cell = row.Cells[i];
 
                         // 读取单元格内容
-                        string cellTextFirst = row.Cells[0].FirstParagraph.ToString(Aspose.Words.SaveFormat.Text).Trim(); 
+                        string cellTextFirst = row.Cells[0].FirstParagraph.ToString(Aspose.Words.SaveFormat.Text).Trim();
 
                         if (cellTextFirst.Contains("舱位"))
                         {
@@ -2321,11 +2353,11 @@ FROM
             bookMarkDic.Add("ClientUnit1", di.ClientUnit);
             bookMarkDic.Add("VisitCountry1", di.VisitCountry);
             bookMarkDic.Add("DayCount", di.VisitDays.ToString());
-            bookMarkDic.Add("VisitingArea", di.VisitDate.ToString("yyyy年MM月dd日")+"-"+di.VisitEndDate.ToString("yyyy年MM月dd日"));
+            bookMarkDic.Add("VisitingArea", di.VisitDate.ToString("yyyy年MM月dd日") + "-" + di.VisitEndDate.ToString("yyyy年MM月dd日"));
             bookMarkDic.Add("CityPath1", cityPath);
             bookMarkDic.Add("CityPath2", cityPath);
 
-            Table contractTable  = (Table)doc.GetChild(NodeType.Table, 1, true);
+            Table contractTable = (Table)doc.GetChild(NodeType.Table, 1, true);
 
             if (contractTable != null)
             {
@@ -2639,7 +2671,7 @@ FROM
 
             jw.Msg = "生成成功!";
             jw.Code = 200;
-            jw.Data = new { Url = AppSettingsHelper.Get("WordBaseUrl") + savePaht.Replace(AppSettingsHelper.Get("WordBasePath"), AppSettingsHelper.Get("WordFtpPath"))};
+            jw.Data = new { Url = AppSettingsHelper.Get("WordBaseUrl") + savePaht.Replace(AppSettingsHelper.Get("WordBasePath"), AppSettingsHelper.Get("WordFtpPath")) };
             return Ok(jw);
         }
 
@@ -3378,29 +3410,29 @@ FROM
                                 var roomTotal = 0.00M;
                                 if (hotelReservations.SingleRoomPrice > 0)
                                 {
-                                    var fee = hotelReservations.SingleRoomPrice * hotelReservations.SingleRoomCount * (int)hotel_days;
-                                    roomFeestr1 += $"<span style='width:70px;display: inline-block;'></span>单间:{hotelReservations.SingleRoomPrice:#0.00} * {hotelReservations.SingleRoomCount}间 * {(int)hotel_days}晚 = {fee:#0.00}<br/>";
+                                    var fee = hotelReservations.SingleRoomPrice * hotelReservations.SingleRoomCount * hotel_days;
+                                    roomFeestr1 += $"<span style='width:70px;display: inline-block;'></span>单间:{hotelReservations.SingleRoomPrice:#0.00} * {hotelReservations.SingleRoomCount}间 * {hotel_days}晚 = {fee:#0.00}<br/>";
                                     //__isSingle = true;
                                     roomTotal += fee;
                                 }
                                 if (hotelReservations.DoubleRoomPrice > 0)
                                 {
-                                    var fee = hotelReservations.DoubleRoomPrice * hotelReservations.DoubleRoomCount * (int)hotel_days;
-                                    roomFeestr1 += $"<span style='width:70px;display: inline-block;'></span>双人间:{hotelReservations.DoubleRoomPrice:#0.00} * {hotelReservations.DoubleRoomCount}间 * {(int)hotel_days}晚 = {fee:#0.00}<br/>";
+                                    var fee = hotelReservations.DoubleRoomPrice * hotelReservations.DoubleRoomCount * hotel_days;
+                                    roomFeestr1 += $"<span style='width:70px;display: inline-block;'></span>双人间:{hotelReservations.DoubleRoomPrice:#0.00} * {hotelReservations.DoubleRoomCount}间 * {hotel_days}晚 = {fee:#0.00}<br/>";
                                     // __isDouble = true;
                                     roomTotal += fee;
                                 }
                                 if (hotelReservations.SuiteRoomPrice > 0)
                                 {
-                                    var fee = hotelReservations.SuiteRoomPrice * hotelReservations.SuiteRoomCount * (int)hotel_days;
-                                    roomFeestr1 += $"<span style='width:70px;display: inline-block;'></span>套房:{hotelReservations.SuiteRoomPrice:#0.00} * {hotelReservations.SuiteRoomCount}间 * {(int)hotel_days}晚 = {fee:#0.00}<br/>";
+                                    var fee = hotelReservations.SuiteRoomPrice * hotelReservations.SuiteRoomCount * hotel_days;
+                                    roomFeestr1 += $"<span style='width:70px;display: inline-block;'></span>套房:{hotelReservations.SuiteRoomPrice:#0.00} * {hotelReservations.SuiteRoomCount}间 * {hotel_days}晚 = {fee:#0.00}<br/>";
                                     //__isSuite = true;
                                     roomTotal += fee;
                                 }
                                 if (hotelReservations.OtherRoomPrice > 0)
                                 {
-                                    var fee = hotelReservations.OtherRoomPrice * hotelReservations.OtherRoomCount * (int)hotel_days;
-                                    roomFeestr1 += $"<span style='width:70px;display: inline-block;'></span>其他:{hotelReservations.OtherRoomPrice:#0.00} * {hotelReservations.OtherRoomCount}间 * {(int)hotel_days}晚 = {fee:#0.00}<br/>";
+                                    var fee = hotelReservations.OtherRoomPrice * hotelReservations.OtherRoomCount * hotel_days;
+                                    roomFeestr1 += $"<span style='width:70px;display: inline-block;'></span>其他:{hotelReservations.OtherRoomPrice:#0.00} * {hotelReservations.OtherRoomCount}间 * {hotel_days}晚 = {fee:#0.00}<br/>";
                                     //__isOther = true;
                                     roomTotal += fee;
                                 }
@@ -4154,7 +4186,7 @@ FROM
                 throw;
             }
         }
-        
+
         /// <summary>
         /// 机票费用录入列表
         /// </summary>
@@ -4179,7 +4211,7 @@ FROM
                 throw;
             }
         }
-        
+
         /// <summary>
         /// 根据id查询费用录入信息
         /// </summary>
@@ -4196,7 +4228,7 @@ FROM
             }
             return Ok(JsonView(true, groupData.Msg, groupData.Data));
         }
-        
+
         /// <summary>
         /// 机票费用录入操作(Status:1.新增,2.修改)
         /// </summary>
@@ -4215,8 +4247,15 @@ FROM
             #region 应用推送
             try
             {
+                var diId = dto.AirTicketResOpData.DiId;
+
                 int ccpId = groupData.Data.GetType().GetProperty("ccpId").GetValue(groupData.Data, null);
                 int sign = groupData.Data.GetType().GetProperty("sign").GetValue(groupData.Data, null);
+                int dataId = groupData.Data.GetType().GetProperty("dataId").GetValue(groupData.Data, null);
+
+                //自动审核
+                var autoAdit = await _feeAuditRep.FeeAutomaticAudit(5, diId, dataId);
+
 
                 await AppNoticeLibrary.SendChatMsg_GroupStatus_ApplyFee(ccpId, sign, QiyeWeChatEnum.GuoJiaoLeaderChat);
 
@@ -4224,7 +4263,6 @@ FROM
                 var userIds = new List<int>() { 21 };
                 string title = $"系统通知";
                 string content = "";
-                var diId = dto.AirTicketResOpData.DiId;
                 var groupInfo = await _groupRepository.Query(x => x.Id == diId).FirstAsync();
                 var ccpInfo = await _sqlSugar.Queryable<Grp_CreditCardPayment>().Where(x => x.Id == ccpId).FirstAsync();
                 if (dto.Status == 1) content = $"[新增-机票费用录入({groupInfo?.TeamName ?? "-"})]一项费用:{(ccpInfo.PayMoney * ccpInfo.DayRate).ToString("#0.00")} CNY;";
@@ -4244,6 +4282,22 @@ FROM
             return Ok(JsonView(true, groupData.Msg, groupData.Data));
         }
 
+        /// <summary>
+        /// 机票费用录入
+        /// 自动审核测试
+        /// </summary>
+        /// <param name="groupId"></param>
+        /// <param name="Id"></param>
+        /// <returns></returns>
+        [HttpPost]
+        [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
+        public async Task<IActionResult> AirTicketResAutoAuditTest(int groupId, int Id)
+        {
+            var autoAdit = await _feeAuditRep.FeeAutomaticAudit(5, groupId, Id);
+
+            return Ok(JsonView(true, autoAdit.Msg, autoAdit.Data));
+        }
+
         /// <summary>
         /// 根据舱位类型查询接团客户名单信息
         /// </summary>
@@ -4403,7 +4457,7 @@ FROM
                 throw;
             }
         }
-        
+
         /// <summary>
         /// 导出机票录入报表
         /// </summary>
@@ -6163,12 +6217,12 @@ FROM
         /// </summary>
         /// <returns></returns>
         [HttpGet]
-        public async Task<IActionResult> SharedFileInit(int userid ,int portType)
+        public async Task<IActionResult> SharedFileInit(int userid, int portType)
         {
 
-            var marketingDepartmentIds = new List<int> { 6, 26 , 27 , 28 };
+            var marketingDepartmentIds = new List<int> { 6, 26, 27, 28 };
 
-            var isMarketingDepartment  = _sqlSugar.Queryable<Sys_Users>()
+            var isMarketingDepartment = _sqlSugar.Queryable<Sys_Users>()
                 .Where(x => x.IsDel == 0 && marketingDepartmentIds.Contains(x.DepId))
                 .Select(x => x.Id)
                 .ToList()
@@ -6193,7 +6247,7 @@ FROM
 
                 var dropDownGroupList = _sqlSugar.Queryable<Grp_DelegationInfo>()
                     .Where(x => x.IsDel == 0)
-                    .OrderByDescending(x=> x.VisitDate )
+                    .OrderByDescending(x => x.VisitDate)
                     .Select(x => new
                     {
                         x.TeamName,
@@ -6201,7 +6255,7 @@ FROM
                         x.CityId,
                     })
                     .ToList()
-                    .Select(x=>
+                    .Select(x =>
                     {
                         var provinceId = x.CityId;
                         var isDefualtVal = true;
@@ -6784,7 +6838,7 @@ FROM
             var groupNamFirst = groupNameData.FirstOrDefault();
 
             //SetDataInfoView
-            var dataSource = await _sqlSugar.Queryable<Sys_SetData>().Where(x => x.IsDel == 0 && x.STid == 66) .ToListAsync();
+            var dataSource = await _sqlSugar.Queryable<Sys_SetData>().Where(x => x.IsDel == 0 && x.STid == 66).ToListAsync();
 
             var currencyData = dataSource.Where(it => it.STid == 66).ToList(); //所有币种
             List<SetDataInfoView> _CurrencyData = _mapper.Map<List<SetDataInfoView>>(currencyData);
@@ -10511,7 +10565,7 @@ FROM
 
             var dataSource = await _sqlSugar
                 .Queryable<Sys_SetData>()
-                .Where(x => x.IsDel == 0 && (x.STid == 72 || x.STid == 73) && x.Remark.Contains(provinceId.ToString())) 
+                .Where(x => x.IsDel == 0 && (x.STid == 72 || x.STid == 73) && x.Remark.Contains(provinceId.ToString()))
                 .ToListAsync();
 
             var fileTypes = new List<EecSetDataInfoView>();
@@ -11242,7 +11296,7 @@ FROM
             if (id <= 0) //add 
             {
                 //int provinceId = dto.ProvinceId;
-                  int  groupId = dto.DiId;
+                int groupId = dto.DiId;
 
                 //if (provinceId < 1) provinceId = 122;
                 var info = new Grp_EnterExitCost() { DiId = groupId, CurrencyRemark = currencyStr, CreateUserId = dto.CurrUserId };
@@ -11415,7 +11469,7 @@ FROM
         public async Task<IActionResult> EnterExitCostMobileOpSingleCheckbox(EnterExitCostMobileOpSingleCheckboxDto dto)
         {
             int itemTypeId = dto.ItemType, id = dto.Id, currUserId = dto.CurrUserId, diId = dto.DiId, isSelected = dto.IsSelected;
-           // if (provinceId < 1) provinceId = 122;
+            // if (provinceId < 1) provinceId = 122;
             var itemTypes = new List<int>() { 3, 4, 5, 6, 7 };
 
             if (!_portTypeData.Contains(dto.PortType)) return Ok(JsonView(false, MsgTips.Port));
@@ -13766,7 +13820,7 @@ FROM
                     else
                     {
                         var rates = await GeneralMethod.EnterExitCostInitRate();
-                        rates.Insert(0,new CurrencyInfo() { CurrencyCode = "CNY", CurrencyName = "人民币", Rate = 1.00000M });
+                        rates.Insert(0, new CurrencyInfo() { CurrencyCode = "CNY", CurrencyName = "人民币", Rate = 1.00000M });
                         result.Rates = rates.ToArray();
                     }
                 }
@@ -13897,7 +13951,7 @@ FROM
 
             #region 住宿费 
             designer.SetDataSource("AccomTitle", accomCosts?.ItemWrapName ?? "住宿费\r\n(请备注明酒店星级)");
-            if (accomCosts!=null && accomCosts.Infos.Any())
+            if (accomCosts != null && accomCosts.Infos.Any())
             {
                 string currencyName = string.Empty,
                        countryName = string.Empty;
@@ -13990,7 +14044,7 @@ FROM
 
             #region 车辆安排 
             designer.SetDataSource("VehArrangeTitle", vehArranges?.ItemWrapName ?? "车辆安排\r\n(司兼导分开的情况下,车辆品牌、座位及费用)");
-            if (vehArranges!=null&&vehArranges.Infos.Any())
+            if (vehArranges != null && vehArranges.Infos.Any())
             {
                 string currencyName = string.Empty;
                 //decimal rate = 1.0000M;
@@ -14015,7 +14069,7 @@ FROM
             #region 邀请函费
             designer.SetDataSource("InviteCostTitle", inviteCosts?.ItemWrapName ?? "邀请函费用");
             StringBuilder is_label = new StringBuilder();
-            if (inviteCosts != null&&inviteCosts.Infos.Any())
+            if (inviteCosts != null && inviteCosts.Infos.Any())
             {
                 string currencyName = string.Empty;
                 decimal rate = 1.0000M;
@@ -14031,7 +14085,7 @@ FROM
                 if (is_label.HasValue())
                 {
                     //以上小计:28500元(美金汇率:7.5)
-                    string label = string.Format("以上小计:{0}{1}({2}汇率:{3})", inviteCosts.TotalAmt.TruncDecimals(2),"元", currencyName, rate.TruncDecimals(4));
+                    string label = string.Format("以上小计:{0}{1}({2}汇率:{3})", inviteCosts.TotalAmt.TruncDecimals(2), "元", currencyName, rate.TruncDecimals(4));
                     is_label.AppendLine(label);
                 }
             }
@@ -14076,7 +14130,7 @@ FROM
             designer.SetDataSource("VisaInsTitle", visaIns?.ItemWrapName ?? "签证+保险\r\n(单位:元)");
 
             StringBuilder vi_label = new StringBuilder();
-            if (visaIns  != null &&  visaIns.Infos.Any())
+            if (visaIns != null && visaIns.Infos.Any())
             {
                 foreach (var item in visaIns.Infos)
                 {
@@ -14198,7 +14252,7 @@ FROM
             return Ok(JsonView(true, groupData.Msg, groupData.Data));
 
         }
-        
+
         /// <summary>
         /// 根据签证费用Id查询单条数据及c表数据
         /// </summary>
@@ -14215,7 +14269,7 @@ FROM
             }
             return Ok(JsonView(true, groupData.Msg, groupData.Data));
         }
-        
+
         /// <summary>
         /// 签证费用删除
         /// </summary>
@@ -14253,7 +14307,7 @@ FROM
             return Ok(JsonView(true, "删除成功!"));
 
         }
-        
+
         /// <summary>
         /// 签证费用录入下拉框初始化
         /// </summary>
@@ -16058,7 +16112,7 @@ FROM
                     x.Id,
                 }).ToList(),
                 baoPi = _GroupCostParameterRepository.GetBaoPi(diid),
-                blackCodeIsTrue = _sqlSugar.Queryable<Air_TicketBlackCode>().Where(x=>x.IsDel == 0 && x.DiId == diid).Any() , //create.Code == 0 ? true : false,
+                blackCodeIsTrue = _sqlSugar.Queryable<Air_TicketBlackCode>().Where(x => x.IsDel == 0 && x.DiId == diid).Any(), //create.Code == 0 ? true : false,
                 hotelIsTrue = hotelIsTrue,
             }));
         }
@@ -16143,7 +16197,7 @@ FROM
         {
             if (dto.Diid <= 0 || dto.Userid <= 0 || dto.ToGroupId <= 0)
             {
-                return Ok(JsonView(false,"参数有误!"));
+                return Ok(JsonView(false, "参数有误!"));
             }
 
             #region 复制团组成本
@@ -18112,10 +18166,10 @@ FROM
         [HttpPost]
         public IActionResult CraeteGroupCostTravel(GroupCostInItDto dto)
         {
-            var jw = JsonView(false,"Error");
+            var jw = JsonView(false, "Error");
             var Create = _sqlSugar.Queryable<Air_TicketBlackCode>()
                                    .Where(x => x.IsDel == 0 && x.DiId == dto.Diid)
-                                   .Select(x=> new
+                                   .Select(x => new
                                    {
                                        x.Id,
                                        x.Title
@@ -18528,9 +18582,9 @@ ORDER by  gctggrc.id DESC
                 airHotelPriceList.Add(new
                      AirHotelPrice
                 {
-                     Name = "经济舱TBR",
-                     Price = rightSum + air + hotel,
-                     Count = result["经济舱TBR"] * 2
+                    Name = "经济舱TBR",
+                    Price = rightSum + air + hotel,
+                    Count = result["经济舱TBR"] * 2
                 });
                 allPrice += (rightSum + air + hotel) * result["经济舱TBR"] * 2;
             }
@@ -18652,7 +18706,7 @@ AirHotelPrice
             foreach (var item in airSouer.Keys)
             {
                 var find = airHotelPriceList.FirstOrDefault(x => x.Name == item);
-                if (find !=  null && find.Count > 0)
+                if (find != null && find.Count > 0)
                 {
                     if (item.Contains("TBR"))
                     {
@@ -18722,7 +18776,7 @@ AirHotelPrice
             }
 
             var costTypeHotelNumbers = await _sqlSugar.Queryable<Grp_CostTypeHotelNumber>()
-                                                        .FirstAsync(x=>x.Type == "Default" && x.Diid == dto.Diid && x.IsDel == 0);
+                                                        .FirstAsync(x => x.Type == "Default" && x.Diid == dto.Diid && x.IsDel == 0);
             if (costTypeHotelNumbers == null)
             {
                 return Ok(JsonView(false, "团组成本不存在!"));
@@ -18807,7 +18861,7 @@ AirHotelPrice
             {
                 { "经济舱", new[] { "TBR", "SGR", "JSES", "SUITE" } },
                 { "公务舱", new[] { "SUITE", "JSES", "SGR" } },
-                { "头等舱", new[] { "SUITE", "JSES" } } 
+                { "头等舱", new[] { "SUITE", "JSES" } }
             };
 
             var result = new Dictionary<string, int>();
@@ -18817,7 +18871,7 @@ AirHotelPrice
                 // 获取当前舱位的匹配规则
                 if (flightRoomMatchingRules.TryGetValue(flight, out string[] roomTypes))
                 {
-                    MatchRooms(ref hotelRooms,ref flights, roomTypes, flight,ref result);
+                    MatchRooms(ref hotelRooms, ref flights, roomTypes, flight, ref result);
                 }
             }
 
@@ -18971,8 +19025,8 @@ AirHotelPrice
 
             #endregion
 
-            designer.SetDataSource("AllPrice","总金额:" + allPrice.ToString("#0.00"));
-            string savePaht = AppSettingsHelper.Get("ExcelBasePath") + "GroupCostQuotations/" + di.TeamName +"_详细报批费用.xls";
+            designer.SetDataSource("AllPrice", "总金额:" + allPrice.ToString("#0.00"));
+            string savePaht = AppSettingsHelper.Get("ExcelBasePath") + "GroupCostQuotations/" + di.TeamName + "_详细报批费用.xls";
             var ws = designer.Workbook.Worksheets[0];
             foreach (var Rowindex in hideRowsList)
             {
@@ -18988,7 +19042,7 @@ AirHotelPrice
 
         }
 
-        private void MatchRooms(ref Dictionary<string, int> hotelRooms,ref Dictionary<string, int> flights, string[] roomTypes, string flightType,ref Dictionary<string, int> result)
+        private void MatchRooms(ref Dictionary<string, int> hotelRooms, ref Dictionary<string, int> flights, string[] roomTypes, string flightType, ref Dictionary<string, int> result)
         {
             foreach (var roomType in roomTypes)
             {
@@ -20032,7 +20086,7 @@ AirHotelPrice
                     builder.Writeln(@$"VOUCHER No:{item.CheckNumber}   DATE: {item.CreateTime.ToString("yyyy-MM-dd")}");
 
 
-                     builder.StartTable();
+                    builder.StartTable();
 
                     // 设置边框颜色
                     builder.CellFormat.Borders.Top.Color = System.Drawing.Color.Black;
@@ -22230,7 +22284,7 @@ AirHotelPrice
                 string clients = kimiApiResult_JObject["content"].ToString();
 
                 string startStr = "```json", endStr = "```";
-                
+
                 // 判断并清除开头部分
                 if (clients.StartsWith(startStr))
                 {
@@ -22269,7 +22323,7 @@ AirHotelPrice
                     company = dc.CompanyFullName;
                     job = dc.Job;
 
-                    if (dc1 != null && !string.IsNullOrEmpty(dc1.CompanyFullName)  )
+                    if (dc1 != null && !string.IsNullOrEmpty(dc1.CompanyFullName))
                     {
                         //查询对照表
                         Res_CompanyEnglishComparison tempCec = listCEC.FirstOrDefault(s => s.zhName.Contains(dc1.CompanyFullName.ToString().Trim()));
@@ -23921,7 +23975,8 @@ And (UnitName != '' Or UnitName != null) {sqlWhere}");
                     item.Title = "未设置名称数据" + count;
                 }
                 count++;
-            };
+            }
+            ;
 
             if (group == null)
             {

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 314 - 283
OASystem/OASystem.Api/Controllers/PersonnelModuleController.cs


+ 7 - 0
OASystem/OASystem.Api/Controllers/ResourceController.cs

@@ -8,8 +8,10 @@ using OASystem.Domain.Dtos.Groups;
 using OASystem.Domain.Entities.Groups;
 using OASystem.Domain.ViewModels.Groups;
 using OASystem.Infrastructure.Repositories.Groups;
+using System.Collections.Generic;
 using System.Data;
 using System.Diagnostics;
+using System.Linq;
 using static OASystem.API.OAMethodLib.JWTHelper;
 
 namespace OASystem.API.Controllers
@@ -4659,6 +4661,11 @@ WHERE
             return Ok(await _mediaSupplierRep.SoftDel(dto));
         }
 
+        
+
+
+
+
         #endregion
 
         #region 保险国家基础费用

+ 272 - 0
OASystem/OASystem.Api/Controllers/SystemController.cs

@@ -3261,5 +3261,277 @@ And u.UId = {0} And u.FId = 1 ", dto.UserId);
 
         #endregion
 
+
+        #region 资料相关Excel 导入
+        /// <summary>
+        /// excel导入 策划部供应商资料
+        /// </summary>
+        /// <param name="file"></param>
+        /// <param name="currUserId">录入人userId</param>
+        /// <returns></returns>
+        [HttpPost]
+        [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
+        public async Task<IActionResult> ExcelImportMediaSupplier(IFormFile file, [FromQuery] int currUserId = 258)
+        {
+            // 检查文件是否为空
+            if (file == null || file.Length == 0)
+            {
+                return Ok(JsonView(false, "请选择文件!"));
+            }
+
+            // 文件签名验证
+            var perExtensions = new[] { ".xls", ".xlsx" };
+            Dictionary<string, List<byte[]>> fileSignature = CommonFun.FileSignature;
+            fileSignature = fileSignature.Where(pair => perExtensions.Contains(pair.Key)).ToDictionary(pair => pair.Key, pair => pair.Value);
+
+            // 文件扩展名验证
+            var ext = Path.GetExtension(file.FileName).ToLowerInvariant();
+            if (string.IsNullOrEmpty(ext) || !fileSignature.ContainsKey(ext))
+            {
+                return Ok(JsonView(false, "不支持的文件类型!"));
+            }
+
+            using (var memoryStream = new MemoryStream())
+            {
+                await file.CopyToAsync(memoryStream);
+
+                // 检查文件签名
+                var fileData = memoryStream.ToArray();
+                var signatures = fileSignature[ext];
+                bool signatureValid = signatures.Any(signature =>
+                    fileData.Take(signature.Length).SequenceEqual(signature));
+
+                if (!signatureValid)
+                {
+                    return Ok(JsonView(false, "文件内容与类型不匹配!"));
+                }
+            }
+
+            // 保存文件到服务器
+            var uploadsFolder = @$"D:\FTP\File\OA2023\Office\Excel\MediaSupplierExcelImportFile";
+            if (!Directory.Exists(uploadsFolder))
+            {
+                Directory.CreateDirectory(uploadsFolder);
+            }
+
+            var fileName = CommonFun.ValidFileName(file.Name);
+
+            var filePath = Path.Combine(uploadsFolder, fileName);
+            using (var stream = new FileStream(filePath, FileMode.Create))
+            {
+                await file.CopyToAsync(stream);
+            }
+
+            Workbook workbook = new Workbook(filePath);
+
+            // 获取第一个工作表
+            Worksheet worksheet = workbook.Worksheets[0];
+
+            // 获取表头(第一行作为列名)
+            int headerRowIndex = 0;
+            Row headerRow = worksheet.Cells.Rows[headerRowIndex];
+            int colCount = worksheet.Cells.MaxDataColumn + 1;
+
+            // 动态存储列名
+            var datas = new List<Res_MediaSuppliers>();
+
+            var typeDatas = await _sqlSugar.Queryable<Sys_SetData>()
+               .Where(x => x.IsDel == 0 && x.STid == 21)
+               .Select(x => new { x.Id, Text = x.Name })
+               .ToListAsync();
+
+            // 遍历数据行(从第二行开始)
+            int rowCount = worksheet.Cells.MaxDataRow + 1;
+            var msgs = new StringBuilder();
+            for (int row = headerRowIndex + 2; row < rowCount; row++)
+            {
+                var cellVal1 = worksheet.Cells[row, 0].Value;    //序号
+                var cellVal2 = worksheet.Cells[row, 1].Value;    //供应商类型
+                var cellVal3 = worksheet.Cells[row, 2].Value;    //地区
+                var cellVal4 = worksheet.Cells[row, 3].Value;    //城市
+                var cellVal5 = worksheet.Cells[row, 4].Value;    //单位名称
+                var cellVal6 = worksheet.Cells[row, 5].Value;    //单位联系人
+                var cellVal7 = worksheet.Cells[row, 6].Value;    //性别
+                var cellVal8 = worksheet.Cells[row, 7].Value;    //联系电话
+                var cellVal9 = worksheet.Cells[row, 8].Value;    //电子邮件
+                var cellVal10 = worksheet.Cells[row, 9].Value;   //单位缩写
+                var cellVal11 = worksheet.Cells[row, 10].Value;  //职位
+                var cellVal12 = worksheet.Cells[row, 11].Value;  //传真号码
+                var cellVal13 = worksheet.Cells[row, 12].Value;  //微信
+                var cellVal14 = worksheet.Cells[row, 13].Value;  //单位地址
+                var cellVal15 = worksheet.Cells[row, 14].Value;  //备注
+
+                int typeId = typeDatas.FirstOrDefault(x => x.Text == cellVal2?.ToString())?.Id ?? 0;
+                if (typeId < 1)
+                {
+                    var name = cellVal5?.ToString() ?? $"序号:{cellVal1?.ToString() ?? "-"}";
+                    msgs.AppendLine($"[{name}]未设置供应商类型!请手动录入!!!");
+                    continue;
+                }
+
+                var rowData = new Res_MediaSuppliers()
+                {
+                    TypeId = typeId,
+                    Privince = cellVal3?.ToString() ?? "",
+                    City = cellVal4?.ToString() ?? "",
+                    UnitName = cellVal5?.ToString() ?? "",
+                    Contact = cellVal6?.ToString() ?? "",
+                    Sex = string.IsNullOrEmpty(cellVal7?.ToString() ?? "") ? -1 : cellVal7.ToString().Equals("男") ? 0 : 1,
+                    Tel = cellVal8?.ToString() ?? "",
+                    Email = cellVal9?.ToString() ?? "",
+                    UnitAbbreviation = cellVal10?.ToString() ?? "",
+                    Post = cellVal11?.ToString() ?? "",
+                    Fax = cellVal12?.ToString() ?? "",
+                    WeChat = cellVal13?.ToString() ?? "",
+                    UnitAddress = cellVal14?.ToString() ?? "",
+                    Remark = cellVal15?.ToString() ?? "",
+                    CreateUserId = currUserId
+
+                };
+
+                datas.Add(rowData); // 将当前行数据添加到集合中
+            }
+
+            if (datas.Any())
+            {
+                var insert = await _sqlSugar.Insertable(datas).ExecuteCommandAsync();
+                if (insert > 0)
+                {
+                    return Ok(JsonView(true, $"导入成功!count:{insert} warningMsg:{msgs.ToString()}"));
+                }
+            }
+            return Ok(JsonView(false, "excel导入失败!"));
+        }
+
+
+        /// <summary>
+        /// excel导入 策划部供应商资料
+        /// </summary>
+        /// <returns></returns>
+        [HttpPost]
+        [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
+        public async Task<IActionResult> CarDataSouceExcelTemp()
+        {
+            var url = $"http://132.232.92.186:24/Office/Excel/CarDataSouceImportFile/op地接供应商资料收集模板.xlsx";
+            return Ok(JsonView(true, url));
+        }
+
+        /// <summary>
+        /// excel导入 车公司资料
+        /// </summary>
+        /// <param name="file"></param>
+        /// <param name="currUserId">录入人userId</param>
+        /// <returns></returns>
+        [HttpPost]
+        [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
+        public async Task<IActionResult> ExcelImportCarDataSouce(IFormFile file, [FromQuery] int currUserId = 208)
+        {
+            // 检查文件是否为空
+            if (file == null || file.Length == 0)
+            {
+                return Ok(JsonView(false, "请选择文件!"));
+            }
+
+            // 文件签名验证
+            var perExtensions = new[] { ".xls", ".xlsx" };
+            Dictionary<string, List<byte[]>> fileSignature = CommonFun.FileSignature;
+            fileSignature = fileSignature.Where(pair => perExtensions.Contains(pair.Key)).ToDictionary(pair => pair.Key, pair => pair.Value);
+
+            // 文件扩展名验证
+            var ext = Path.GetExtension(file.FileName).ToLowerInvariant();
+            if (string.IsNullOrEmpty(ext) || !fileSignature.ContainsKey(ext))
+            {
+                return Ok(JsonView(false, "不支持的文件类型!"));
+            }
+
+            using (var memoryStream = new MemoryStream())
+            {
+                await file.CopyToAsync(memoryStream);
+
+                // 检查文件签名
+                var fileData = memoryStream.ToArray();
+                var signatures = fileSignature[ext];
+                bool signatureValid = signatures.Any(signature =>
+                    fileData.Take(signature.Length).SequenceEqual(signature));
+
+                if (!signatureValid)
+                {
+                    return Ok(JsonView(false, "文件内容与类型不匹配!"));
+                }
+            }
+
+            // 保存文件到服务器
+            var uploadsFolder = @$"D:\FTP\File\OA2023\Office\Excel\CarDataSouceImportFile";
+            if (!Directory.Exists(uploadsFolder))
+            {
+                Directory.CreateDirectory(uploadsFolder);
+            }
+
+            var fileName = CommonFun.ValidFileName(file.Name);
+
+            var filePath = Path.Combine(uploadsFolder, fileName);
+            using (var stream = new FileStream(filePath, FileMode.Create))
+            {
+                await file.CopyToAsync(stream);
+            }
+
+            Workbook workbook = new Workbook(filePath);
+
+            // 获取第一个工作表
+            Worksheet worksheet = workbook.Worksheets[0];
+
+            // 获取表头(第一行作为列名)
+            int headerRowIndex = 0;
+            Row headerRow = worksheet.Cells.Rows[headerRowIndex];
+            int colCount = worksheet.Cells.MaxDataColumn + 1;
+
+            // 动态存储列名
+            var datas = new List<Res_CarData>();
+
+            // 遍历数据行(从第三行开始)
+            int rowCount = worksheet.Cells.MaxDataRow + 1;
+            var msgs = new StringBuilder();
+            for (int row = headerRowIndex + 2; row < rowCount; row++)
+            {
+                var cellVal1 = worksheet.Cells[row, 0].Value;    //地区
+                var cellVal2 = worksheet.Cells[row, 1].Value;    //公司名称
+                var cellVal3 = worksheet.Cells[row, 2].Value;    //公司地址
+                var cellVal4 = worksheet.Cells[row, 3].Value;    //联系人
+                var cellVal5 = worksheet.Cells[row, 4].Value;    //联系电话
+                var cellVal6 = worksheet.Cells[row, 5].Value;    //电子邮箱
+                var cellVal7 = worksheet.Cells[row, 6].Value;    //其他信息
+
+                var dtTimeNoew = DateTime.Now;
+                var rowData = new Res_CarData()
+                {
+                    UnitArea = cellVal1?.ToString() ?? "",
+                    UnitName = cellVal2?.ToString() ?? "",
+                    Address = cellVal3?.ToString() ?? "",
+                    Contact = cellVal4?.ToString() ?? "",
+                    ContactTel = cellVal5?.ToString() ?? "",
+                    ContactEmail = cellVal6?.ToString() ?? "",
+                    OtherInfo = cellVal7?.ToString() ?? "",
+                    LastUpdateTime = dtTimeNoew,
+                    LastUpdateUserId = currUserId,
+                    CreateTime = dtTimeNoew,
+                    CreateUserId = currUserId,
+                    Remark = $"excel导入添加!"
+                };
+                EncryptionProcessor.EncryptProperties(rowData);
+                datas.Add(rowData); 
+            }
+
+            if (datas.Any())
+            {
+                var insert = await _sqlSugar.Insertable(datas).ExecuteCommandAsync();
+                if (insert > 0)
+                {
+                    return Ok(JsonView(true, $"导入成功!count:{insert} warningMsg:{msgs.ToString()}"));
+                }
+            }
+            return Ok(JsonView(false, "excel导入失败!"));
+        }
+        #endregion
+
     }
 }

+ 159 - 2
OASystem/OASystem.Api/OAMethodLib/QiYeWeChatAPI/AppNotice/Library.cs

@@ -1,10 +1,13 @@
 using OASystem.Domain.Dtos.Groups;
 using OASystem.Domain.Entities.Financial;
 using OASystem.Domain.Entities.Groups;
+using OASystem.Domain.Entities.PersonnelModule;
 using OASystem.Domain.ViewModels.CRM;
 using OASystem.Domain.ViewModels.Groups;
 using OASystem.Domain.ViewModels.QiYeWeChat;
+using OASystem.Domain.ViewModels.Statistics;
 using OASystem.Infrastructure.Repositories.Groups;
+using Quartz.Logging;
 
 namespace OASystem.API.OAMethodLib.QiYeWeChatAPI.AppNotice
 {
@@ -40,7 +43,6 @@ namespace OASystem.API.OAMethodLib.QiYeWeChatAPI.AppNotice
 
         #endregion
 
-
         #region 确认出团
 
         /// <summary>
@@ -1182,13 +1184,168 @@ namespace OASystem.API.OAMethodLib.QiYeWeChatAPI.AppNotice
         }
         #endregion
 
+        #region 物资通知
+
+        /// <summary>
+        /// 物资领用通知
+        /// 接收者:审核节点相关审核人
+        /// </summary>
+        /// <param name="dataId"></param>
+        /// <param name="diId"></param>
+        /// <param name="operationId"></param>
+        /// <returns></returns>
+        public static async Task<bool> SendUserMsg_CompanyShare_ToHR(int dataId,int diId, int operationId)
+        {
+            //企微通知
+            var userIds = new List<string>()
+            {
+                "208", //雷怡
+                "374", //罗颖
+            };
+
+            var isCheckValuable = false;
+            var valuableUserNames = new List<string>();
+
+            //根据审核节点的审核人,发送通知
+            var flow = _grpDeleRep._sqlSugar.Queryable<Sys_AuditFlow>().First(x => x.IsDel == 0 && x.BusinessType == 1 && x.BusinessId == dataId);
+            if (flow != null)
+            {
+                var auditNode = _grpDeleRep._sqlSugar
+                    .Queryable<Sys_AuditTemplateNode>()
+                    .First(x => x.IsDel == 0 && x.TemplateId == flow.TemplateId && x.Id == flow.CurrentNodeId);
+                if (auditNode != null)
+                { 
+                    var auditUserList = _grpDeleRep._sqlSugar.Queryable<Sys_AuditTemplateNodeUser>()
+                        .Where(x => x.IsDel == 0 && x.NodeId == auditNode.Id)
+                        .Select(x => new {
+                            x.UserId,
+                            x.UserName
+                        })
+                        .ToList();
+                    if (auditUserList.Any())
+                    {
+                        if (auditUserList.Count() > 1) isCheckValuable = true;
+
+                        userIds.AddRange(auditUserList.Select(x => x.UserId.ToString()).ToList());
+                        userIds = userIds.Distinct().ToList();
+                        valuableUserNames.AddRange( auditUserList.Select(x => x.UserName).ToList());
+                    }
+                }
+            }
+
+            Grp_DelegationInfo groupInfo = _grpDeleRep.Query<Grp_DelegationInfo>(s => s.Id == diId).First();
+            var operationName = _grpDeleRep.Query<Sys_Users>(s => s.IsDel == 0 && s.Id == operationId).First()?.CnName ?? "Unknown";
+
+            var groupName = diId switch
+            {
+                0 => "其他物资(公司内部物资)",
+                -1 => "拜访客户所使用的物资",
+                -2 => "库存调整",
+                _ => groupInfo?.TeamName ?? "-"
+            };
+
+
+            var receiveInfo = _grpDeleRep._sqlSugar.Queryable<Pm_GoodsReceive>().First(x => x.IsDel == 0 && x.Id == dataId);
+            if (receiveInfo == null) return false;
+            var receiveDetails = _grpDeleRep._sqlSugar
+                .Queryable<Pm_GoodsReceiveDetails>()
+                .LeftJoin<Pm_GoodsInfo>((x,y) => x.GoodsId == y.Id)
+                .Where(x => x.IsDel == 0 && x.GoodsReceiveId == dataId)
+                .Select((x,y) => new { 
+                    y.Name,
+                    x.Quantity,
+                    y.Unit
+                })
+                .ToList();
+
+            if (!receiveDetails.Any()) return false;
+
+            var goodsMsg = new StringBuilder();
+            foreach (var info in receiveDetails)
+            {
+                goodsMsg.AppendLine($">- {info.Name}:{info.Quantity:#0.00} {info.Unit}");
+            }
+
+            var groupLabel = string.Empty;
+            if (string.IsNullOrEmpty(groupName) || !groupName.Equals("-"))
+            {
+                groupLabel = $">团组归属:<font color='info'>{groupName}</font>";
+            }
+
+            //普通物品审批消息通知
+            string resMsg = string.Format(@" ` 物资领用申请通知 `  
+
+> ` {0} `提交物资领用申请: 
+
+{1}
+
+>**物资明细**   
+{2}
+>用途:<font color='comment'>{3}</font> 
+>申请时间:<font color='comment'>{4}</font> 
+
+[详细信息请前往OA系统查看](http://oa.pan-american-intl.com:4399/)   ",
+operationName,
+groupLabel,
+goodsMsg,
+receiveInfo.Reason,
+DateTime.Now.ToString("yyyy-MM-dd HH:mm"));
+
+            //贵重物品审批消息通知
+            if (isCheckValuable)
+            {
+                var auditUserLabel = string.Empty;
+                foreach (var userName in valuableUserNames)
+                {
+                    auditUserLabel += $"@{userName} ";
+                }
+
+                resMsg = string.Format(@" ` 【或签审批】物资领用(任一人审批即可)通知 `  
+
+>{0}
+> ` {1} `提交物资领用申请,您被列为或签审批人: 
+
+**或签规则**  
+• 您与其他{2}人并行审批  
+• 任意一人通过即视为本环节通过  
+• 任意一人拒绝即视为终止流程  
+
+{3}
+
+>**物资明细**   
+{4}
+>用途:<font color='comment'>{5}</font> 
+>申请时间:<font color='comment'>{6}</font> 
+
+[详细信息请前往OA系统查看](http://oa.pan-american-intl.com:4399/)   ",
+auditUserLabel,
+operationName,
+valuableUserNames.Count() - 1 ,
+groupLabel,
+goodsMsg,
+receiveInfo.Reason,
+DateTime.Now.ToString("yyyy-MM-dd HH:mm"));
+            }
+
+            List<string> qwUserIdList = GetQiyeChatUserIdList(userIds);
+            ResponseBase result = await _qiYeWeChatApiService.GroupStatus_SendMessage_ToUser_Markdown(qwUserIdList, resMsg);
+            if (result.errcode != 0)
+            {
+                //抄送日志 
+                return false;
+            }
+
+            return true;
+        }
+        #endregion
+
         #region Helper
 
         private static string getClientNameStr(List<SimplClientInfo> list, string origin)
         {
             string result = origin;
 
-            if (Regex.Match(origin, @"\d+,?").Value.Length > 0)
+            if (Regex.Match(origin, @"\d +,?").Value.Length > 0)
             {
                 string[] temparr = origin.Split(',');
                 string fistrStr = temparr[0];

+ 7 - 0
OASystem/OASystem.Domain/ViewModels/Financial/Fin_ForeignReceivablesView.cs

@@ -349,6 +349,13 @@ namespace OASystem.Domain.ViewModels.Financial
         /// </summary>
         public string visitDate { get; set; }
 
+        ///// <summary>
+        ///// 是否显示红色
+        ///// true : 是
+        ///// false : 否
+        ///// </summary>
+        //public bool isShowRed { get; set; } = false;
+
         /// <summary>
         /// 应收
         /// </summary>

+ 1 - 0
OASystem/OASystem.Domain/ViewModels/Groups/OrderPreInfoView.cs

@@ -65,6 +65,7 @@ namespace OASystem.Domain.ViewModels.Groups
 
     public class GrpOrderPreInfoMobileView : GrpOrderPreInfoBasicView
     {
+        public string GroupName { get; set; } = "";
         public GrpOrderPreItemMobileView[] Items { get; set; }
     }
 

+ 23 - 0
OASystem/OASystem.Domain/ViewModels/PersonnelModule/GoodsInfoView.cs

@@ -201,6 +201,14 @@ namespace OASystem.Domain.ViewModels.PersonnelModule
         public string GoodsType { get; set; }
 
         public string GoodsDetails { get; set; }
+        public GoodsStorageAuditPerView[] AuditPers { get; set; }
+
+        /// <summary>
+        /// 审核权限
+        /// true:有
+        /// false:无
+        /// </summary>
+        public bool IsAuditPer { get; set; } = false;
 
     }
 
@@ -209,7 +217,22 @@ namespace OASystem.Domain.ViewModels.PersonnelModule
 
         public int GoodsTypeId { get; set; }
 
+        /// <summary>
+        /// 是否贵重物品
+        /// true:贵重物品
+        /// false:非贵重物品
+        /// </summary>
         public bool IsValuable { get; set; } = false;
+
+        //public GoodsStorageAuditPerView[] AuditPers { get; set; }
+
+        /// <summary>
+        /// 审核权限
+        /// true:有
+        /// false:无
+        /// </summary>
+        public bool IsAuditPer { get; set; } = false;
+
     }
 
     /// <summary>

+ 2 - 2
OASystem/OASystem.Infrastructure/Repositories/Groups/AirTicketResRepository.cs

@@ -618,7 +618,7 @@ namespace OASystem.Infrastructure.Repositories.Groups
                         });
                         CommitTran();
 
-                        var data = new { ccpId = id, sign = 1 };
+                        var data = new { ccpId = id, sign = 1, dataId = grp_CreditCard.CId };
                         return result = new Result() { Code = 0, Msg = "添加成功!", Data = data };
                     }
                     else
@@ -844,7 +844,7 @@ namespace OASystem.Infrastructure.Repositories.Groups
                         {
                             Grp_CreditCardPayment ccp = Query<Grp_CreditCardPayment>(a => a.Id == dto.CardPaymentOpData.Id).First();
 
-                            var data = new { ccpId = ccp.Id, sign = 2 };
+                            var data = new { ccpId = ccp.Id, sign = 2, dataId = grp_CreditCard.CId };
                             result = new Result() { Code = 0, Msg = "修改成功!", Data = data };
                         }
                     }

+ 225 - 45
OASystem/OASystem.Infrastructure/Repositories/Groups/FeeAuditRepository.cs

@@ -5,6 +5,7 @@ using OASystem.Domain;
 using OASystem.Domain.Entities.Groups;
 using OASystem.Domain.Entities.Resource;
 using OASystem.Domain.ViewModels.Groups;
+using SqlSugar;
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -31,6 +32,7 @@ namespace OASystem.Infrastructure.Repositories.Groups
         /// 2.op 79
         /// 3.其他费用-出行物资 98
         /// 4.保险 82
+        /// 5.机票 85
         /// </param>
         /// <param name="diId">团组Id</param>
         /// <param name="dataId">数据Id(模块类型主表Id)</param>
@@ -41,22 +43,31 @@ namespace OASystem.Infrastructure.Repositories.Groups
             if (diId < 1) { _view.Msg = MsgTips.DiId; return _view; }
             if (dataId < 1) { _view.Msg = MsgTips.Id; return _view; }
 
+            var groupDetails = _sqlSugar.Queryable<Grp_DelegationInfo>().Where(x => x.IsDel == 0 && x.Id == diId).First();
+            if (groupDetails == null)
+            {
+                _view.Msg = $"团组信息为空,不可自动审核!";
+                return _view;
+            }
+
             var stids = new List<int>() { 17, 66, 91 };
             var setData = _sqlSugar.Queryable<Sys_SetData>().Where(x => x.IsDel == 0 && stids.Contains(x.STid)).ToList();
-            string _teamCurrency = string.Empty;
 
-            decimal _teamRate = 0.00M;
-            var costContents = new List<GroupCostAuditView>();
-            if (feeType != 4)
-            {
-                var groupInfo = _sqlSugar.Queryable<Grp_GroupCostParameter>().Where(x => x.IsDel == 0 && x.DiId == diId).First();
-                if (groupInfo == null) { _view.Msg = $"团组成本信息未填写!"; return _view; }
-                _teamCurrency = groupInfo.Currency;
-                _teamRate = groupInfo.Rate;
+            var groupInfo = _sqlSugar.Queryable<Grp_GroupCostParameter>().Where(x => x.IsDel == 0 && x.DiId == diId).First();
+            if (groupInfo == null) { _view.Msg = $"团组成本信息未填写!"; return _view; }
+            string _teamCurrency = groupInfo.Currency;
+            decimal _teamRate = groupInfo.Rate;
 
-                //币种验证  统一为currencycode三字码
-                if (int.TryParse(_teamCurrency, out int currency)) _teamCurrency = setData.Find(x => x.Id == currency)?.Name ?? "";
+            //币种验证  统一为currencycode三字码
+            if (int.TryParse(_teamCurrency, out int currency)) _teamCurrency = setData.Find(x => x.Id == currency)?.Name ?? "";
 
+            var costContents = new List<GroupCostAuditView>();
+            var subFeeTypeIds = new int[] { 
+                4, // 保险 82
+                5, // 机票 85
+            };
+            if (!subFeeTypeIds.Contains(feeType))
+            {
                 string costContentSql = $"Select * From Grp_GroupCost";
                 costContents = _sqlSugar.SqlQueryable<GroupCostAuditView>(costContentSql).Where(x => x.IsDel == 0 && x.Diid == diId).ToList();
 
@@ -88,7 +99,7 @@ namespace OASystem.Infrastructure.Repositories.Groups
                     }
                 }
             }
-            
+
             if (feeType == 1)
             {
                 //1089	对冲账或其他 不在审核范围
@@ -289,71 +300,71 @@ namespace OASystem.Infrastructure.Repositories.Groups
 
                     //车费 91
                     var opCarCost = item.FirstOrDefault(x => x.SId == 91);
-                    if (opCarCost != null) 
+                    if (opCarCost != null)
                         if (opCarCost.Price * _opRate * _opPayPercentage > _teamRate * opCostInfo.Sum(x => x.CarFee) * _opPayPercentage) isAutoAudit = false;
                     //982 车超时费 -- 暂无
                     //92  导游费
                     var opGuideCost = item.FirstOrDefault(x => x.SId == 92);
-                    if (opGuideCost != null) 
+                    if (opGuideCost != null)
                         if (opGuideCost.Price * _opRate * _opPayPercentage > _teamRate * opCostInfo.Sum(x => x.GuideFee) * _opPayPercentage) isAutoAudit = false;
                     //94  导游景点费
                     var opGuideScenicCost = item.FirstOrDefault(x => x.SId == 94);
-                    if (opGuideScenicCost != null) 
+                    if (opGuideScenicCost != null)
                         if (opGuideScenicCost.Price * _opRate * _opPayPercentage > _teamRate * opCostInfo.Sum(x => x.GuideScenicFee) * _opPayPercentage) isAutoAudit = false;
                     //95  导游小费
                     var opGuideTipCost = item.FirstOrDefault(x => x.SId == 95);
-                    if (opGuideTipCost != null) 
+                    if (opGuideTipCost != null)
                         if (opGuideTipCost.Price * _opRate * _opPayPercentage > _teamRate * opCostInfo.Sum(x => x.GuideTipFee) * _opPayPercentage) isAutoAudit = false;
                     //983 导游餐补
                     var opGuideMealCost = item.FirstOrDefault(x => x.SId == 983);
-                    if (opGuideMealCost != null) 
+                    if (opGuideMealCost != null)
                         if (opGuideMealCost.Price * _opRate * _opPayPercentage > _teamRate * opCostInfo.Sum(x => x.GuideMealFee) * _opPayPercentage) isAutoAudit = false;
                     //984 导游房补
                     var opGuideRoomCost = item.FirstOrDefault(x => x.SId == 984);
-                    if (opGuideRoomCost != null) 
+                    if (opGuideRoomCost != null)
                         if (opGuideRoomCost.Price * _opRate * _opPayPercentage > _teamRate * opCostInfo.Sum(x => x.GuideRoomFee) * _opPayPercentage) isAutoAudit = false;
                     //985 导游交通
                     var opGuideTrafficCost = item.FirstOrDefault(x => x.SId == 985);
-                    if (opGuideTrafficCost != null) 
+                    if (opGuideTrafficCost != null)
                         if (opGuideTrafficCost.Price * _opRate * _opPayPercentage > _teamRate * opCostInfo.Sum(x => x.GuideTrafficFee) * _opPayPercentage) isAutoAudit = false;
                     //96  接送机费 -- 暂无
                     //97  其他费用 -- 暂无
                     //979 司机工资
                     var opDriverCost = item.FirstOrDefault(x => x.SId == 979);
-                    if (opDriverCost != null) 
+                    if (opDriverCost != null)
                         if (opDriverCost.Price * _opRate > _teamRate * _opPayPercentage * opCostInfo.Sum(x => x.DriverFee) * _opPayPercentage) isAutoAudit = false;
                     //980 司机小费
                     var opDriverTipCost = item.FirstOrDefault(x => x.SId == 980);
-                    if (opDriverTipCost != null) 
+                    if (opDriverTipCost != null)
                         if (opDriverTipCost.Price * _opRate * _opPayPercentage > _teamRate * opCostInfo.Sum(x => x.DriverTipFee) * _opPayPercentage) isAutoAudit = false;
                     //981 司机餐补
                     var opDriverMealCost = item.FirstOrDefault(x => x.SId == 981);
-                    if (opDriverMealCost != null) 
+                    if (opDriverMealCost != null)
                         if (opDriverMealCost.Price * _opRate * _opPayPercentage > _teamRate * opCostInfo.Sum(x => x.DriverMealFee) * _opPayPercentage) isAutoAudit = false;
                     //988 客户早餐费用
                     var opClientBreakfastCost = item.FirstOrDefault(x => x.SId == 988);
-                    if (opClientBreakfastCost != null) 
+                    if (opClientBreakfastCost != null)
                         if (opClientBreakfastCost.Price * _opRate * _opPayPercentage > _teamRate * opCostInfo.Sum(x => x.ClientBreakfastFee) * _opPayPercentage) isAutoAudit = false;
                     //93  客户午餐费用
                     var opClientLunchCost = item.FirstOrDefault(x => x.SId == 93);
-                    if (opClientLunchCost != null) 
+                    if (opClientLunchCost != null)
                         if (opClientLunchCost.Price * _opRate * _opPayPercentage > _teamRate * opCostInfo.Sum(x => x.ClientLunchFee) * _opPayPercentage) isAutoAudit = false;
                     //989 客户晚餐费用
                     var opClientDinnerCost = item.FirstOrDefault(x => x.SId == 989);
-                    if (opClientDinnerCost != null) 
+                    if (opClientDinnerCost != null)
                         if (opClientDinnerCost.Price * _opRate * _opPayPercentage > _teamRate * opCostInfo.Sum(x => x.ClientDinnerFee) * _opPayPercentage) isAutoAudit = false;
                     //990 景点门票费
                     var opScenicTicketCost = item.FirstOrDefault(x => x.SId == 990);
-                    if (opScenicTicketCost != null) 
+                    if (opScenicTicketCost != null)
                         if (opScenicTicketCost.Price * _opRate * _opPayPercentage > _teamRate * opCostInfo.Sum(x => x.ScenicTicketFee) * _opPayPercentage) isAutoAudit = false;
                     //991 饮料/零食/水果
                     var opDrinkSnackFruitCost = item.FirstOrDefault(x => x.SId == 991);
-                    if (opDrinkSnackFruitCost != null) 
+                    if (opDrinkSnackFruitCost != null)
                         if (opDrinkSnackFruitCost.Price * _opRate * _opPayPercentage > _teamRate * opCostInfo.Sum(x => x.DrinkSnackFruitFee) * _opPayPercentage) isAutoAudit = false;
                     //992 住补费用 -- 暂无
                     //994 翻译费
                     var opTranslatorCost = item.FirstOrDefault(x => x.SId == 994);
-                    if (opTranslatorCost != null) 
+                    if (opTranslatorCost != null)
                         if (opTranslatorCost.Price * _opRate * _opPayPercentage > _teamRate * opCostInfo.Sum(x => x.TranslatorFee) * _opPayPercentage) isAutoAudit = false;
                     //1059    导游超时费用 -- 暂无
                     //1070    尾款金额 -- 暂无
@@ -397,9 +408,7 @@ namespace OASystem.Infrastructure.Repositories.Groups
 
                 var isAutoAudit = false;
                 var currModule = 98; //其他款项
-                int groupSize = 0; // 团组人数
-                var groupDetails = await _sqlSugar.Queryable<Grp_DelegationInfo>().Where(x => x.IsDel == 0 && x.Id == diId).FirstAsync();
-                if (groupDetails != null) groupSize = groupDetails.VisitPNumber;
+                int groupSize =  groupDetails.VisitPNumber;
 
                 decimal otherSubTotal = costContents.Sum(x => x.TeFee);
                 decimal groupCostCNYTotal = costContents.Sum(x => x.TeFee) * _teamRate * groupSize; //团组成本出行物资总金额
@@ -496,13 +505,6 @@ namespace OASystem.Infrastructure.Repositories.Groups
             {
                 #region 保险费用录入自动审核
                 var currModule = 82;
-                var groupDetails = _sqlSugar.Queryable<Grp_DelegationInfo>().Where(x => x.IsDel == 0 && x.Id == diId).First(); 
-                if (groupDetails == null)
-                {
-                    _view.Msg = $"团组信息为空,不可自动审核!";
-                    return _view;
-                }
-
                 var insuranceCountryCostData = _sqlSugar.Queryable<Res_BasicInsuranceCost>().Where(x => x.IsDel == 0).ToList();
                 if (!insuranceCountryCostData.Any())
                 {
@@ -601,11 +603,11 @@ namespace OASystem.Infrastructure.Repositories.Groups
 
                 //自动审核
                 var ccpUpdate = _sqlSugar.Updateable<Grp_CreditCardPayment>()
-                                      .SetColumns(it => it.IsAuditGM == 3)
-                                      .SetColumns(it => it.AuditGMOperate == 4)
-                                      .SetColumns(it => it.AuditGMDate == DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"))
-                                      .Where(s => s.DIId == diId && s.CTable == currModule && s.CId == dataId)
-                                      .ExecuteCommand();
+                    .SetColumns(it => it.IsAuditGM == 3)
+                    .SetColumns(it => it.AuditGMOperate == 4)
+                    .SetColumns(it => it.AuditGMDate == DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"))
+                    .Where(s => s.DIId == diId && s.CTable == currModule && s.CId == dataId)
+                    .ExecuteCommand();
                 if (ccpUpdate > 0)
                 {
                     _view.Code = 200;
@@ -615,6 +617,148 @@ namespace OASystem.Infrastructure.Repositories.Groups
                 return _view;
                 #endregion
             }
+            else if (feeType == 5)
+            {
+                #region 机票费用自动审核只处理舱位相关的费用
+
+                var currModule = 85;
+                var auditFeeTypeIds = new List<int>() {
+                    457,   //头等舱
+                    458,   //公务舱
+                    459,   //超经舱
+                    460,   //经济舱
+                    1430,  //公务舱(实际经济舱)
+                    1431,  //头等舱(实际公务舱)
+                    1432,  //头等舱(实际经济舱)
+                };
+
+                var airInfo = await _sqlSugar.Queryable<Grp_AirTicketReservations>()
+                    .InnerJoin<Grp_CreditCardPayment>((x, y) => x.Id == y.CId && y.CTable == currModule && y.IsDel == 0)
+                    .Where((x, y) => x.Id == dataId && x.IsDel == 0 && auditFeeTypeIds.Contains(x.CType))
+                    .Select((x,y) => new { 
+                        x.Id,
+                        CcpId = y.Id,
+                        x.Price,
+                        x.CType,
+                        x.ClientNum,
+                        x.DIId
+                    })
+                    .FirstAsync();
+                if (airInfo == null)
+                {
+                    _view.Msg = $"机票信息为空或费用类型不在自动审核范围内,不可自动审核!";
+                    return _view;
+                }
+
+                //团组成本 经济舱、头等舱、公务舱
+                int ecoPaxCount = groupInfo.JJCRS,   //经济舱人数
+                    firstClassCnt = groupInfo.TDCRS, //头等舱人数
+                    bizClassCnt = groupInfo.GWCRS;   //公务舱人数
+                decimal ecoCost = groupInfo.JJCCB,   //经济舱成本费用
+                        firstCost = groupInfo.TDCCB, //头等舱成本费用
+                        bizCost = groupInfo.GWCCB;   //公务舱成本费用
+                decimal ecoTotalCost = ecoPaxCount * ecoCost,       //经济舱成本费用合计
+                        firstTotalCost = firstClassCnt * firstCost, //头等舱成本费用合计
+                        bizTotalCost = bizClassCnt * bizCost;       //公务舱成本费用合计
+
+                int currAirType = airInfo.CType; //当前舱位类型
+                int currAirTypeCnt = 0;          //当前舱位人数
+                //decimal currAirFee = 0.00M;      //当前舱位录入费用
+                decimal currAirCost = 0.00M;     //当前舱位成本费用
+
+
+                switch (airInfo.CType)
+                {
+                    //头等舱
+                    case 457:
+                        currAirTypeCnt = groupInfo.TDCRS; //头等舱人数
+                        currAirCost = currAirTypeCnt * groupInfo.TDCCB; //头等舱成本费用合计
+                        break;
+                    //公务舱
+                    case 458:
+                        currAirTypeCnt = groupInfo.GWCRS; //公务舱人数
+                        currAirCost = currAirTypeCnt * groupInfo.GWCCB; //公务舱成本费用合计
+                        break;
+                    case 459: //超经舱
+                        currAirTypeCnt = groupInfo.JJCRS; //经济舱人数
+                        currAirCost = currAirTypeCnt * groupInfo.JJCCB; //经济舱成本费用合计
+                        break;
+                    case 460: //经济舱
+                        currAirTypeCnt = groupInfo.JJCRS; //经济舱人数
+                        currAirCost = currAirTypeCnt * groupInfo.JJCCB; //经济舱成本费用合计
+                        break;
+                    case 1430: //公务舱(实际经济舱)
+                        currAirTypeCnt = groupInfo.GWCRS; //公务舱人数
+                        currAirCost = currAirTypeCnt * groupInfo.GWCCB; //公务舱成本费用合计
+                        break;
+                    case 1431: //头等舱(实际公务舱)
+                        currAirTypeCnt = groupInfo.TDCRS; //头等舱人数
+                        currAirCost = currAirTypeCnt * groupInfo.TDCCB; //头等舱成本费用合计
+                        break;
+                    case 1432: //头等舱(实际经济舱)
+                        currAirTypeCnt = groupInfo.TDCRS; //头等舱人数
+                        currAirCost = currAirTypeCnt * groupInfo.TDCCB; //头等舱成本费用合计
+                        break;
+                    default:
+                        _view.Msg = $"机票费用类型不在自动审核范围内,不可自动审核!";
+                        return _view;
+                }
+
+                var currAirTypeDatas = await _sqlSugar.Queryable<Grp_AirTicketReservations>()
+                    .Where(x => x.IsDel == 0 && x.DIId == diId && x.CType == airInfo.CType && x.ClientNum == currAirTypeCnt)
+                    .ToListAsync();
+                var airTypeText = airInfo.CType switch
+                {
+                    457 => "头等舱",
+                    458 => "公务舱",
+                    459 => "超经舱",
+                    460 => "经济舱",
+                    1430 => "公务舱(实际经济舱)",
+                    1431 => "头等舱(实际公务舱)",
+                    1432 => "头等舱(实际经济舱)",
+                    _ => "未知舱位"
+                };
+
+                if (!currAirTypeDatas.Any())
+                {
+                    _view.Msg = $"{airTypeText}机票费用数据未填写或者舱位人数不匹配,不可自动审核!";
+                    return _view;
+                }
+
+                //验证费用类型
+                if (!currAirTypeDatas.Any(x => x.Id == airInfo.Id))
+                {
+                    _view.Msg = $"机票费用({airTypeText})超出团组成本费用";
+                    return _view;
+                }
+
+                //验证是否超出舱位成本费用
+                decimal currAirTypeFee = currAirTypeDatas.Sum(x => x.Price);
+                if (currAirTypeFee > currAirCost)
+                {
+                    _view.Msg = $"机票费用({airTypeText})超出团组成本费用";
+                    QuashAudit(currModule, diId, currAirTypeDatas.Select(x => x.Id).ToArray());
+                    return _view;
+                }
+
+                //执行自动审核及相关字段更改
+                var upd = _sqlSugar.Updateable<Grp_CreditCardPayment>()
+                    .SetColumns(x => x.IsAuditGM == 3)
+                    .SetColumns(x => x.AuditGMOperate == 4)
+                    .SetColumns(x => x.AuditGMDate == DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"))
+                    .Where(x => x.Id == airInfo.CcpId)
+                    .ExecuteCommand();
+                if (upd > 0)
+                {
+                    _view.Code = StatusCodes.Status200OK;
+                    _view.Msg = "自动审核执行成功";
+                    return _view;
+                }
+                _view.Msg = "自动审核执行失败";
+                return _view;
+
+                #endregion
+            }
             else _view.Msg = $"请传入有效的feeType参数";
 
             return _view;
@@ -625,7 +769,7 @@ namespace OASystem.Infrastructure.Repositories.Groups
         /// </summary>
         /// <param name="type">
         /// 酒店 76
-        /// op   79
+        /// op 79
         /// </param>
         /// <param name="diId"></param>
         /// <param name="dataId"></param>
@@ -653,7 +797,43 @@ namespace OASystem.Infrastructure.Repositories.Groups
             return false;
         }
 
-        //
+
+        /// <summary>
+        /// air 撤销自动审核的数据
+        /// </summary>
+        /// <param name="type">
+        /// 机票
+        /// </param>
+        /// <param name="diId"></param>
+        /// <param name="dataId"></param>
+        /// <returns></returns>
+        private bool QuashAudit(int type, int diId, int[] dataId)
+        {
+            //撤销该条数据的自动审核 --> 该条数据的审核状态是自动审核  3 --> 0
+            var ccpInfos = _sqlSugar.Queryable<Grp_CreditCardPayment>()
+                .Where(s => s.DIId == diId && s.CTable == type && dataId.Contains(s.CId) && s.IsAuditGM == 3)
+                .ToList();
+            if (ccpInfos.Any())
+            {
+                ccpInfos.ForEach(x =>
+                {
+                    x.IsAuditGM = 0;
+                    x.AuditGMOperate = 0;
+                    x.AuditGMDate = string.Empty;
+                });
+
+                var ccpUpd = _sqlSugar.Updateable(ccpInfos)
+                    .UpdateColumns(x => new { x.IsAuditGM, x.AuditGMOperate, x.AuditGMDate })
+                    .ExecuteCommand();
+                if (ccpUpd > 0)
+                {
+                    return true;
+                }
+            }
+
+            return false;
+        }
+
         /// <summary>
         /// 费用自动审核
         /// </summary>

+ 9 - 0
OASystem/OASystem.Infrastructure/Repositories/Groups/GroupOrderPreInfoRepository.cs

@@ -213,6 +213,15 @@ namespace OASystem.Infrastructure.Repositories.Groups
             view.Id = id;
             view.Name = info.Name;
             view.GroupId = info.GroupId;
+            if (info.GroupId > 0)
+            {
+                var groupInfo = await _sqlSugar.Queryable<Grp_DelegationInfo>().FirstAsync(x => x.IsDel == 0 && x.Id == info.GroupId);
+                if (groupInfo != null)
+                {
+                    view.GroupId = groupInfo.Id;
+                    view.GroupName = groupInfo.TeamName;
+                }
+            }
             var items = await _sqlSugar.Queryable<Sys_FormTemp, Grp_OrderPreItem, Sys_SetData, Sys_SetData>((ft, opi, sd1, sd2) =>
                 new JoinQueryInfos(
                     JoinType.Inner, ft.Id == opi.FormTempId,

+ 282 - 113
OASystem/OASystem.Infrastructure/Repositories/PersonnelModule/GoodsRepository.cs

@@ -1,19 +1,14 @@
 using Aspose.Cells;
 using AutoMapper;
 using EyeSoft.Collections.Generic;
-using EyeSoft.Runtime.InteropServices;
 using Newtonsoft.Json;
-using Npgsql.Replication.PgOutput.Messages;
 using OASystem.Domain;
 using OASystem.Domain.Dtos.PersonnelModule;
-using OASystem.Domain.Dtos.System;
 using OASystem.Domain.Entities.Groups;
 using OASystem.Domain.Entities.PersonnelModule;
 using OASystem.Domain.ViewModels.PersonnelModule;
 using OASystem.Infrastructure.Repositories.System;
 using OASystem.Infrastructure.Tools;
-using System.Linq;
-using System.Text.RegularExpressions;
 
 namespace OASystem.Infrastructure.Repositories.PersonnelModule
 {
@@ -114,7 +109,7 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
             };
 
             _jv.Code = StatusCodes.Status200OK;
-            _jv.Data = new { goodsTypeData = typeData, stockStatus = stockStatus, receiveStatus = receiveStatus, groupNameData = groupData, userNameData = userData };
+            _jv.Data = new { goodsTypeData = typeData, stockStatus, receiveStatus, groupNameData = groupData, userNameData = userData };
             _jv.Msg = $"操作成功";
             return _jv;
         }
@@ -428,11 +423,13 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
                 .OrderByDescending(gs => gs.CreateTime)
                 .ToPageListAsync(dto.PageIndex, dto.PageSize, total);
 
-            
+
             foreach (var item in data)
             {
-                var auditDeps = new List<GoodsStorageAuditPerView>();
-                auditDeps.Add(new() { AuditPer = hrAuditPer, AuditDep = GoodsAuditDepEnum.Hr, ButtonText = GoodsAuditDepEnum.Hr.GetEnumDescription() });
+                var auditDeps = new List<GoodsStorageAuditPerView>
+                {
+                    new() { AuditPer = hrAuditPer, AuditDep = GoodsAuditDepEnum.Hr, ButtonText = GoodsAuditDepEnum.Hr.GetEnumDescription() }
+                };
                 var auditPer = GoodsAuditType(item.GoodsType);
                 if (auditPer)
                 {
@@ -603,10 +600,11 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
         /// <returns></returns>
         public List<Pm_GoodsAudit> GoodsStorageConfirm(int auditType, int dataId, int currUserId)
         {
-            var goodsAuditList = new List<Pm_GoodsAudit>();
-
-            goodsAuditList.Add(new Pm_GoodsAudit(auditType, GoodsAuditDepEnum.Hr, dataId, GoodsConfirmEnum.WaitConfirm, currUserId));
-            goodsAuditList.Add(new Pm_GoodsAudit(auditType, GoodsAuditDepEnum.Financial, dataId, GoodsConfirmEnum.WaitConfirm, currUserId));
+            var goodsAuditList = new List<Pm_GoodsAudit>
+            {
+                new(auditType, GoodsAuditDepEnum.Hr, dataId, GoodsConfirmEnum.WaitConfirm, currUserId),
+                new(auditType, GoodsAuditDepEnum.Financial, dataId, GoodsConfirmEnum.WaitConfirm, currUserId)
+            };
 
             return goodsAuditList;
         }
@@ -719,7 +717,7 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
                 {
                     confirmStatus = GoodsConfirmEnum.Confirmed;
                 }
-                else if (preInfos.Where(x => x.AuditStatus == GoodsConfirmEnum.Confirmed).Count() >= 1)
+                else if (preInfos.Count(x => x.AuditStatus == GoodsConfirmEnum.Confirmed) >= 1)
                 {
                     confirmStatus = GoodsConfirmEnum.PartConfirmed;
                 }
@@ -831,7 +829,7 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
         /// 2:出库审核
         /// </param>
         /// <returns></returns>
-        public (bool, GoodsAuditDepEnum) GoodsAuditDep(int userId, GoodsAuditDepEnum auditDepEnum, int auditType = 1)
+        public static (bool, GoodsAuditDepEnum) GoodsAuditDep(int userId, GoodsAuditDepEnum auditDepEnum, int auditType = 1)
         {
             if (userId < 1) return (false, GoodsAuditDepEnum.Hr);
 
@@ -857,7 +855,7 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
         /// 2:出库审核
         /// </param>
         /// <returns></returns>
-        public List<GoodsAuditDepView> GoodsStorageConfirmAuditDep(int auditType = 1)
+        public static List<GoodsAuditDepView> GoodsStorageConfirmAuditDep(int auditType = 1)
         {
             var auditList = new List<GoodsAuditDepView>();
 
@@ -945,9 +943,9 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
             }
 
             var goodsInfo = await _sqlSugar.Queryable<Pm_GoodsInfo>().FirstAsync(x => x.Id == goodsId);
-            goodsInfo.SQ_Total = goodsInfo.SQ_Total - delAgoQuantity;
-            goodsInfo.StockQuantity = goodsInfo.StockQuantity - delAgoQuantity;
-            goodsInfo.PriceTotal = goodsInfo.PriceTotal - delAgoTotalPrice;
+            goodsInfo.SQ_Total -= delAgoQuantity;
+            goodsInfo.StockQuantity -= delAgoQuantity;
+            goodsInfo.PriceTotal -= delAgoTotalPrice;
             goodsInfo.LastUpdateUserId = userId;
             goodsInfo.LastUpdateTime = DateTime.Now;
 
@@ -1059,8 +1057,10 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
             }
 
             //载入模板
-            WorkbookDesigner designer = new WorkbookDesigner();
-            designer.Workbook = new Workbook(excelTempPath);
+            WorkbookDesigner designer = new()
+            {
+                Workbook = new Workbook(excelTempPath)
+            };
 
             designer.SetDataSource("Export", data);
 
@@ -1241,7 +1241,7 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
                     Id = gr.Id,
                     GroupId = gr.GroupId,
                     GroupName = di.TeamName,
-                    GoodsId = gr.GoodsId,
+                    GoodsId = grd.GoodsId,
                     GoodsName = gi.Name,
                     GoodsTypeId = gi.Type,
                     GoodsType = sd.Name,
@@ -1304,8 +1304,10 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
                 }
 
                 //载入模板
-                WorkbookDesigner designer = new WorkbookDesigner();
-                designer.Workbook = new Workbook(excelTempPath);
+                WorkbookDesigner designer = new()
+                {
+                    Workbook = new Workbook(excelTempPath)
+                };
 
                 var tableData = await data.ToListAsync();
                 foreach (var item in tableData)
@@ -1325,9 +1327,10 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
                         var oldAuditDatas = await _sqlSugar.Queryable<Pm_GoodsAudit>()
                            .LeftJoin<Sys_Users>((x, u) => x.AuditUserId == u.Id)
                            .Where((x, u) => x.IsDel == 0 && x.Type == 2 && x.DataId == item.Id)
-                           .Select((x, u) => new { 
-                                x.AuditTime,
-                                u.CnName
+                           .Select((x, u) => new
+                           {
+                               x.AuditTime,
+                               u.CnName
                            })
                            .ToListAsync();
                         if (oldAuditDatas.Any())
@@ -1340,11 +1343,12 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
                             else item.AuditTime = DateTime.Now;
                         }
                         else
-                        { 
+                        {
                             var newAuditDatas = await _sqlSugar.Queryable<Sys_AuditRecord>()
-                                .InnerJoin<Sys_AuditFlow>((x,y) => x.FlowId == y.Id)
+                                .InnerJoin<Sys_AuditFlow>((x, y) => x.FlowId == y.Id)
                                .Where((x, y) => x.IsDel == 0 && y.BusinessType == 1 && y.BusinessId == item.Id)
-                               .Select((x, y) => new {
+                               .Select((x, y) => new
+                               {
                                    x.AuditTime,
                                    x.AuditorName
                                })
@@ -1396,7 +1400,8 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
                     var oldAuditDatas = await _sqlSugar.Queryable<Pm_GoodsAudit>()
                        .LeftJoin<Sys_Users>((x, u) => x.AuditUserId == u.Id)
                        .Where((x, u) => x.IsDel == 0 && x.Type == 2 && x.DataId == item.Id)
-                       .Select((x, u) => new {
+                       .Select((x, u) => new
+                       {
                            x.AuditTime,
                            u.CnName
                        })
@@ -1415,7 +1420,8 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
                         var newAuditDatas = await _sqlSugar.Queryable<Sys_AuditRecord>()
                             .InnerJoin<Sys_AuditFlow>((x, y) => x.FlowId == y.Id)
                            .Where((x, y) => x.IsDel == 0 && y.BusinessType == 1 && y.BusinessId == item.Id)
-                           .Select((x, y) => new {
+                           .Select((x, y) => new
+                           {
                                x.AuditTime,
                                x.AuditorName
                            })
@@ -1432,6 +1438,17 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
                         }
                     }
                 }
+
+                //权限前台验证
+                var auditPers = new List<GoodsStorageAuditPerView>
+                {
+                    new() { AuditPer = true, AuditDep = GoodsAuditDepEnum.Hr, ButtonText = GoodsAuditDepEnum.Hr_Reception.GetDescription() }
+                };
+                if (_goodsTypeIds.Contains(item.GoodsTypeId))
+                {
+                    auditPers.Add(new() { AuditPer = true, AuditDep = GoodsAuditDepEnum.Hr, ButtonText = GoodsAuditDepEnum.Hr.GetDescription() });
+                }
+                item.AuditPers = auditPers.ToArray();
             }
 
             if (dto.PortType == 2 || dto.PortType == 3)
@@ -1503,8 +1520,8 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
                             {
                                 subData.Add(new
                                 {
-                                    StorageId = item.StorageId,
-                                    BatchNo = storageInfo.BatchNo,
+                                    item.StorageId,
+                                    storageInfo.BatchNo,
                                     RecsiveQuantity = item.Quantity
                                 });
                                 goodsStorageInfoStr += $"物品名称:{data.GoodsName} 批次号:{storageInfo.BatchNo} 领用数量:{item.Quantity} \r\n";
@@ -1572,9 +1589,9 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
             var goodsAuditInfo1 = new Pm_GoodsAudit(2, GoodsAuditDepEnum.Hr_Reception, info.Id, GoodsConfirmEnum.WaitConfirm, currUserId);
             var goodsAuditInfo2 = new Pm_GoodsAudit(2, GoodsAuditDepEnum.Hr, info.Id, GoodsConfirmEnum.WaitConfirm, currUserId);
             var goodsAuditInfos = new List<Pm_GoodsAudit>() { goodsAuditInfo1 };
-            
+
             //状态描述
-            StringBuilder stringBuilder = new StringBuilder();
+            StringBuilder stringBuilder = new();
             stringBuilder.Append($"领用确认:状态:待确认  审核人:-  审核时间:-;<br/>");
 
             if (isAuditPer)
@@ -1665,7 +1682,7 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
         {
             if (idArray.Length < 1) return _jv;
 
-            if (!Enum.IsDefined(typeof(GoodsAuditEnum),(int)auditEnum))
+            if (!Enum.IsDefined(typeof(GoodsAuditEnum), (int)auditEnum))
             {
                 _jv.Msg = $"出库确认状态超出可用范围!";
                 return _jv;
@@ -1752,8 +1769,8 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
             else //单人审核 
             {
                 //领用确认 --> 已确认 / 领用拒绝 --> 已拒绝
-                _jv = await GoodsReceiveOutConfirmingSingle(receiveInfo,userId, currUserName,auditEnum);
-                
+                _jv = await GoodsReceiveOutConfirmingSingle(receiveInfo, userId, currUserName, auditEnum);
+
             }
 
             if (_jv.Code == StatusCodes.Status200OK)
@@ -1977,7 +1994,7 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
             }
 
             //处理状态描述
-            StringBuilder statusDesc = new StringBuilder();
+            StringBuilder statusDesc = new();
 
             var receiveUserName = _sqlSugar.Queryable<Sys_Users>().First(x => x.Id == receiveInfo.AuditUserId)?.CnName ?? "-";
             string receiveStatusDesc = string.Format("{0}:状态:{1}  审核人:{2}  审核时间:{3};<br/>",
@@ -2181,7 +2198,7 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
             }
 
             //处理状态描述
-            StringBuilder statusDesc = new StringBuilder();
+            StringBuilder statusDesc = new();
 
             var receiveUserName = _sqlSugar.Queryable<Sys_Users>().First(x => x.Id == receiveInfo.AuditUserId)?.CnName ?? "-";
             string receiveStatusDesc = string.Format("{0}:状态:{1}  审核人:{2}  审核时间:{3};<br/>",
@@ -2327,7 +2344,7 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
                                 if (newStorageInfo == null) continue;
 
                                 var newEdit = await _sqlSugar.Updateable(newStorageInfo)
-                                        .ReSetValue(x => x.ReceiveQuantity = x.ReceiveQuantity - item.Quantity)
+                                        .ReSetValue(x => x.ReceiveQuantity -= item.Quantity)
                                         .ExecuteCommandAsync();
 
                                 if (newEdit < 1)
@@ -2397,8 +2414,10 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
 
             if (auditInfo == null)
             {
-                auditInfo = new Pm_GoodsAudit(2, depEnum, receiveInfo.Id, auditStatus, userId);
-                auditInfo.AuditUserId = userId;
+                auditInfo = new Pm_GoodsAudit(2, depEnum, receiveInfo.Id, auditStatus, userId)
+                {
+                    AuditUserId = userId
+                };
                 var addStatus = await _sqlSugar.Insertable(auditInfo).ExecuteCommandAsync();
                 if (addStatus < 1)
                 {
@@ -2435,7 +2454,7 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
             }
             auditInfos = auditInfos.OrderBy(x => x.Dep).ToList();
             //处理状态描述
-            StringBuilder statusDesc = new StringBuilder();
+            StringBuilder statusDesc = new();
             foreach (var auditInf in auditInfos)
             {
                 string auditType = auditInf.Dep == GoodsAuditDepEnum.Hr ? "人事部" : "领用确认";
@@ -2611,7 +2630,8 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
             //回滚库存
             var changeGoods = await _sqlSugar
                 .Updateable(goodsInfo)
-                .ReSetValue(it => {
+                .ReSetValue(it =>
+                {
                     it.StockQuantity += receiveInfo.Quantity;
                     it.OQ_Total -= receiveInfo.Quantity;
                     it.LastUpdateTime = DateTime.Now;
@@ -2642,7 +2662,7 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
                 if (newStorageInfo == null) continue;
 
                 var newEdit = await _sqlSugar.Updateable(newStorageInfo)
-                        .ReSetValue(x => x.ReceiveQuantity = x.ReceiveQuantity - item.Quantity)
+                        .ReSetValue(x => x.ReceiveQuantity -= item.Quantity)
                         .ExecuteCommandAsync();
 
                 if (newEdit < 1)
@@ -2669,7 +2689,7 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
         /// <param name="currUserName"></param>
         /// <param name="auditEnum"></param>
         /// <returns></returns>
-        public async Task<JsonView> GoodsReceiveOutConfirmingSingle(Pm_GoodsReceive receiveInfo, int userId,string currUserName,GoodsAuditEnum auditEnum)
+        public async Task<JsonView> GoodsReceiveOutConfirmingSingle(Pm_GoodsReceive receiveInfo, int userId, string currUserName, GoodsAuditEnum auditEnum)
         {
             _jv.Code = StatusCodes.Status400BadRequest;
 
@@ -2740,9 +2760,9 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
             }
 
             //处理状态描述
-            StringBuilder statusDesc = new StringBuilder();
+            StringBuilder statusDesc = new();
             statusDesc.Append(string.Format("领用确认:状态:{0}  审核人:{1}  审核时间:{2};", auditInfo.AuditStatus.GetEnumDescription(), currUserName, currUserOpTime));
-            
+
             //批次库存信息
             string goodsStorageInfo = receiveInfo.GoodsStorageInfo;
 
@@ -2844,7 +2864,8 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
 
                     var changeGoods = await _sqlSugar
                         .Updateable(goodsInfo)
-                        .ReSetValue(it => {
+                        .ReSetValue(it =>
+                        {
                             it.StockQuantity += receiveInfo.Quantity;
                             it.OQ_Total -= receiveInfo.Quantity;
                             it.LastUpdateTime = DateTime.Now;
@@ -2873,7 +2894,7 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
                                 if (newStorageInfo == null) continue;
 
                                 var newEdit = await _sqlSugar.Updateable(newStorageInfo)
-                                        .ReSetValue(x => x.ReceiveQuantity = x.ReceiveQuantity - item.Quantity)
+                                        .ReSetValue(x => x.ReceiveQuantity -= item.Quantity)
                                         .ExecuteCommandAsync();
 
                                 if (newEdit < 1)
@@ -2915,6 +2936,7 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
         /// <returns></returns>
         public async Task<JsonView> GoodsReceiveDel(int id, int currUserId)
         {
+            _jv.Msg = $"操作失败";
             var receiveInfo = await _sqlSugar
                 .Queryable<Pm_GoodsReceive>()
                 .Where(x => x.IsDel == 0 && x.Id == id)
@@ -2925,6 +2947,7 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
                 return _jv;
             }
 
+            _sqlSugar.BeginTran();
             var edit = await _sqlSugar
                 .Updateable<Pm_GoodsReceive>()
                 .SetColumns(x => new Pm_GoodsReceive()
@@ -2935,13 +2958,31 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
                 })
                 .Where(x => x.Id == id)
                 .ExecuteCommandAsync();
-            if (edit > 0)
+            if (edit < 1)
             {
-                _jv.Msg = $"操作成功!";
-                _jv.Code = StatusCodes.Status200OK;
+                _sqlSugar.RollbackTran();
                 return _jv;
             }
+            var editSub = await _sqlSugar
+                .Updateable<Pm_GoodsReceiveDetails>()
+                .SetColumns(x => new Pm_GoodsReceiveDetails()
+                {
+                    IsDel = 1,
+                    DeleteUserId = currUserId,
+                    DeleteTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
+                })
+                .Where(x => x.GoodsReceiveId == id)
+                .ExecuteCommandAsync();
 
+            if (editSub > 0)
+            {
+                _sqlSugar.RollbackTran();
+                return _jv;
+            }
+
+            _sqlSugar.CommitTran();
+            _jv.Msg = $"操作成功!";
+            _jv.Code = StatusCodes.Status200OK;
             return _jv;
         }
 
@@ -3013,8 +3054,13 @@ FROM
   ) Temp ");
 
 
+            var checkValuableUserIds = new List<int>() {
+                343 , //陈湘OAId
+                309 , //赖红燕AId
+            };
+
             var isValueable = false;
-            if (currUserId == 343) //陈湘OAId登录 只显示贵重物品审核信息
+            if (checkValuableUserIds.Contains(currUserId)) //陈湘OAId登录 只显示贵重物品审核信息
             {
                 isValueable = true;
             }
@@ -3024,10 +3070,45 @@ FROM
                 .WhereIF(!string.IsNullOrEmpty(goodsName), x => x.GoodsName.Contains(goodsName))
                 .ToPageListAsync(dto.PageIndex, dto.PageSize, total);
 
+            //普通物品领用审核模板
+            var normAuditTemps = await _approvalProcessRep.GetTemplateByBusinessTypeAsync(2); //普通物品
+
+            var normAuditUsers = new List<GoodsStorageAuditPerView>();
+            normAuditTemps?.TempNodes.ForEach(x =>
+            {
+                var auditDep = GoodsAuditDepEnum.Hr_Reception;
+                if (x.NodeName.Contains("人事部主管/经理审核")) auditDep = GoodsAuditDepEnum.Hr;
+                else if (x.NodeName.Contains("前台审核")) auditDep = GoodsAuditDepEnum.Hr;
+                x.NodeUsers.ForEach(y =>
+                {
+                    var userFlang = false;
+                    if (y.UserId == currUserId) userFlang = true;
+                    var info = new GoodsStorageAuditPerView() { ButtonText = x.NodeName, AuditDep = auditDep, AuditPer = userFlang };
+                    normAuditUsers.Add(info);
+                });
+            });
+
+            //贵重物品领用审核模板
+            var valuableAuditTemps = await _approvalProcessRep.GetTemplateByBusinessTypeAsync(3); //贵重物品
+            var valuableAuditUsers = new List<GoodsStorageAuditPerView>();
+            valuableAuditTemps?.TempNodes.ForEach(x =>
+            {
+                var auditDep = GoodsAuditDepEnum.Hr_Reception;
+                if (x.NodeName.Contains("人事部主管/经理审核")) auditDep = GoodsAuditDepEnum.Hr;
+                else if (x.NodeName.Contains("前台审核")) auditDep = GoodsAuditDepEnum.Hr;
+                x.NodeUsers.ForEach(y =>
+                {
+                    var userFlang = false;
+                    if (y.UserId == currUserId) userFlang = true;
+                    var info = new GoodsStorageAuditPerView() { ButtonText = x.NodeName, AuditDep = auditDep, AuditPer = userFlang };
+                    valuableAuditUsers.Add(info);
+                });
+            });
+
             foreach (var item in view)
             {
                 var details = $"暂无物品信息数据";
-                
+
                 //设置领用详情
                 if (item.GoodsTypeId < 1)
                 {
@@ -3059,16 +3140,17 @@ FROM
                         details = text.ToString();
                     }
                 }
-                else details = $"归属团组:{item.GroupName} <br/><br/>物品名称:{item.GoodsName}   物品类型:{item.GoodsType}   领用数量:{item.Quantity}   备注:{item.Remark}<br/>";
+                else details = $"归属团组/类型:{item.GroupName} <br/><br/>物品名称:{item.GoodsName}   物品类型:{item.GoodsType}   领用数量:{item.Quantity}   备注:{item.Remark}<br/>";
 
                 item.GoodsDetails = details;
 
                 //设置领用状态描述
                 var auditRecords = await _sqlSugar.Queryable<Sys_AuditRecord>()
-                    .InnerJoin<Sys_AuditFlow>((ar,af) => ar.FlowId == af.Id)
+                    .InnerJoin<Sys_AuditFlow>((ar, af) => ar.FlowId == af.Id)
                     .Where((ar, af) => ar.IsDel == 0 && af.BusinessId == item.Id && af.BusinessType == 1)
-                    .Select((ar, af) => new {
-                        NodeId = ar.NodeId,
+                    .Select((ar, af) => new
+                    {
+                        ar.NodeId,
                         ar.NodeName,
                         ar.AuditResult,
                         ar.AuditorName,
@@ -3081,18 +3163,51 @@ FROM
                     var text = new StringBuilder();
                     auditRecords.ForEach(x =>
                     {
-                        var statusText = x.AuditResult switch { 
+                        var statusText = x.AuditResult switch
+                        {
                             0 => "待审核",
                             1 => "已审核",
                             2 => "已拒绝",
                             3 => "无需处理",
                             _ => "未知"
                         };
-                        var str = $"{x.NodeName}:状态:{statusText}  审核人:{x.AuditorName}  审核时间:{x.AuditTime.ToString("yyyy-MM-dd HH:mm:ss")}<br/>";
+
+                        var auditTime = $"-";
+                        if (x.AuditResult == 1 || x.AuditResult == 2 || x.AuditResult == 3) auditTime = x.AuditTime.ToString("yyyy-MM-dd HH:mm:ss");
+
+                        var str = $"{x.NodeName}:状态:{statusText}  审核人:{x.AuditorName}  审核时间:{auditTime}<br/>";
                         text.Append(str);
                     });
                     item.StatusDesc = text.ToString();
                 }
+
+
+                //多情况下审核、操作权限验证
+                if (item.GoodsTypeId == 0)
+                {
+                    int tempId = 2;
+                    if (item.IsValuable) tempId = 3;
+
+                    item.IsAuditPer = await _approvalProcessRep.VerifyAuditAuthAsync(tempId, 1, item.Id, currUserId);
+                }
+                else
+                {
+                    if (item.AuditStatus == GoodsAuditEnum.Pending)
+                    {
+                        item.IsAuditPer = normAuditTemps?.TempNodes.FirstOrDefault()?.NodeUsers.Any(x => x.UserId == currUserId) ?? false;
+                    }
+                    else if (item.AuditStatus == GoodsAuditEnum.OutConfirming)
+                    {
+                        item.IsAuditPer = valuableAuditTemps?.TempNodes.FirstOrDefault(x => x.NodeOrder == 1)?.NodeUsers.Any(x => x.UserId == currUserId) ?? false;
+                    }
+                }
+
+                //前端权限验证
+                if (item.IsValuable)
+                {
+                    item.AuditPers = valuableAuditUsers.ToArray();
+                }
+                else item.AuditPers = normAuditUsers.ToArray();
             }
 
             if (dto.PortType == 2 || dto.PortType == 3)
@@ -3171,6 +3286,47 @@ FROM
                 //物品类型验证
                 if (_goodsTypeIds.Contains(goodsInfo.Type)) isBatchVail = true;
 
+                //入库批次关联领用人 更改批次库存
+                var goodsStorages = await _sqlSugar
+                    .Queryable<Pm_GoodsStorage>()
+                    .Where(x => x.IsDel == 0 &&
+                                x.GoodsId == receiveInfo.GoodsId &&
+                                (x.Quantity - x.ReceiveQuantity) > 0
+                        )
+                    .OrderBy(x => x.CreateTime)
+                    .ToListAsync();
+
+                var goodsReceiveInfos = new List<GoodsReceiveLinkStorageView>();
+                var batchStorageInfos = new List<Pm_GoodsStorage>();
+                var receiveQuantity = 0.00M; //领用总数量
+                foreach (var storage in goodsStorages)
+                {
+                    if (receiveInfo.Quantity == receiveQuantity) break;
+
+                    var thisBatchSurplusQuantity = storage.Quantity - storage.ReceiveQuantity;
+                    if (thisBatchSurplusQuantity <= 0.00M) continue;
+
+                    var thisBatchReceiveQuantity = 0.00M; //此批次领用数量
+                    const decimal unit = 0.50M;
+                    while (receiveQuantity < receiveInfo.Quantity)
+                    {
+                        if (thisBatchSurplusQuantity == thisBatchReceiveQuantity) break;
+
+                        thisBatchReceiveQuantity += unit;
+                        receiveQuantity += unit;
+                    }
+                    goodsReceiveInfos.Add(new GoodsReceiveLinkStorageView
+                    {
+                        StorageId = storage.Id,
+                        Quantity = thisBatchReceiveQuantity
+                    });
+                    storage.ReceiveQuantity += thisBatchReceiveQuantity;
+                    var storageUpd = storage;
+                    //storageUpd.ReceiveQuantity += thisBatchReceiveQuantity;
+                    batchStorageInfos.Add(storageUpd);
+                }
+
+
                 goodsIndex++;
             }
 
@@ -3178,7 +3334,7 @@ FROM
             {
                 receiveInfo.GoodsName = string.Join("、", goodsNames);
             }
-            
+
             //验证领用 添加OR编辑
             var goodsReceiveInfo = await _sqlSugar.Queryable<Pm_GoodsReceive>().FirstAsync(x => x.IsDel == 0 && x.Id == goodsReceiveId);
             if (goodsReceiveInfo == null) //添加
@@ -3220,29 +3376,30 @@ FROM
                     return _jv;
                 }
 
-                //删除旧数据
-                var delStatus = await _sqlSugar.Updateable<Pm_GoodsReceiveDetails>()
-                    .SetColumns(x => new Pm_GoodsReceiveDetails()
-                    {
-                        IsDel = 1,
-                        DeleteUserId = currUserId,
-                        DeleteTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
-                    })
-                    .Where(x => x.GoodsReceiveId == goodsReceiveId)
-                    .ExecuteCommandAsync();
-
-                if (delStatus < 1)
-                {
-                    _jv.Msg = $"领用明细旧数据删除失败!";
-                    _sqlSugar.RollbackTran();
-                    return _jv;
-                }
-
-                //添加新明细数据
+                //更新子表数据
                 if (receiveDetails.Any())
                 {
-                    var addStatus = await _sqlSugar.Insertable(receiveDetails).ExecuteCommandAsync();
-                    if (addStatus < 1)
+                    receiveDetails.ForEach(x => { x.GoodsReceiveId = receiveInfo.Id; });
+
+
+                    var db_receiveDetails = await _sqlSugar.Queryable<Pm_GoodsReceiveDetails>()
+                   .Where(x => x.IsDel == 0 && x.GoodsReceiveId == goodsReceiveId)
+                   .ToListAsync();
+
+                    var toDelete = db_receiveDetails.Where(p => !receiveDetails.Any(np => np.Id == p.Id)).ToList();
+                    if (toDelete.Any())
+                    {
+                        var delStatus = _sqlSugar.Deleteable(toDelete).ExecuteCommand();
+                        if (delStatus < 1)
+                        {
+                            _jv.Msg = $"领用明细旧数据删除失败!";
+                            _sqlSugar.RollbackTran();
+                            return _jv;
+                        }
+                    }
+
+                    var addOrUpdStatus = await _sqlSugar.Storageable<Pm_GoodsReceiveDetails>(receiveDetails.ToList()).ExecuteCommandAsync();
+                    if (addOrUpdStatus < 1)
                     {
                         _jv.Msg = $"领用明细更新失败!";
                         _sqlSugar.RollbackTran();
@@ -3251,7 +3408,6 @@ FROM
                 }
             }
 
-
             #region 审批流程验证、创建
             //审核验证 物品含有贵重物品 使用贵重物品审批流程
             var auditTempInfo = new ApprovalProcessView();
@@ -3337,7 +3493,9 @@ FROM
 
             _sqlSugar.CommitTran();
             _jv.Code = StatusCodes.Status200OK;
+            _jv.Data = new { sign = goodsReceiveId };
             _jv.Msg = $"操作成功!";
+
             return _jv;
         }
 
@@ -3352,7 +3510,6 @@ FROM
             int currUserId = dto.CurrUserId;
             string goodsName = dto.GoodsName;
 
-            
             var showAllPeopleIds = new List<int>() {
                 374, // 罗颖
                 233, // 刘华举
@@ -3363,13 +3520,14 @@ FROM
 
             RefAsync<int> total = 0;
             var receiveList = await _sqlSugar.Queryable<Pm_GoodsReceive>()
-                .LeftJoin<Sys_Users>((x,y) => x.CreateUserId == y.Id)
-                .Where((x, y) => x.IsDel == 0 && x.GoodsId == 0 )
-                .WhereIF(!string.IsNullOrEmpty(goodsName), (x,y) => x.GoodsName.Contains(goodsName))
-                .WhereIF(!isShowAllPeople,(x,y) => x.CreateUserId == currUserId)
+                .LeftJoin<Sys_Users>((x, y) => x.CreateUserId == y.Id)
+                .Where((x, y) => x.IsDel == 0 && x.GoodsId == 0)
+                .WhereIF(!string.IsNullOrEmpty(goodsName), (x, y) => x.GoodsName.Contains(goodsName))
+                .WhereIF(!isShowAllPeople, (x, y) => x.CreateUserId == currUserId)
                 .OrderByDescending((x, y) => x.CreateTime)
-                .Select((x,y) => new GoodsReceiveBatchListView() { 
-                    Id   = x.Id,
+                .Select((x, y) => new GoodsReceiveBatchListView()
+                {
+                    Id = x.Id,
                     GoodsName = x.GoodsName,
                     AccumQty = SqlFunc.Subqueryable<Pm_GoodsReceiveDetails>().Where(z => z.IsDel == 0 && z.GoodsReceiveId == x.Id).Sum(z => z.Quantity),
                     Reason = x.Reason,
@@ -3378,7 +3536,7 @@ FROM
                     Applicant = y.CnName,
                     ApplyTime = x.CreateTime,
                 })
-                .ToPageListAsync(dto.PageIndex,dto.PageSize,total);
+                .ToPageListAsync(dto.PageIndex, dto.PageSize, total);
 
             foreach (var item in receiveList)
             {
@@ -3420,7 +3578,6 @@ FROM
             return _jv;
         }
 
-
         /// <summary>
         /// 物品领用 批量 详情
         /// </summary>
@@ -3438,11 +3595,13 @@ FROM
                 return _jv;
             }
 
-            var info = new GoodsReceiveBatchView();
-            info.Id = receiveInfo.Id;
-            info.GroupId = receiveInfo.GroupId;
-            info.Reason = receiveInfo.Reason;
-            info.Remark = receiveInfo.Remark;
+            var info = new GoodsReceiveBatchView
+            {
+                Id = receiveInfo.Id,
+                GroupId = receiveInfo.GroupId,
+                Reason = receiveInfo.Reason,
+                Remark = receiveInfo.Remark,
+            };
             info.ReceiveDetails = await _sqlSugar
                 .Queryable<Pm_GoodsReceiveDetails>()
                 .LeftJoin<Pm_GoodsInfo>((x, y) => x.GoodsId == y.Id)
@@ -3456,26 +3615,24 @@ FROM
                     Remark = x.Remark,
                 })
                 .ToArrayAsync();
-
             _jv.Code = StatusCodes.Status200OK;
             _jv.Msg = $"操作成功!";
             _jv.Data = info;
             return _jv;
         }
 
-
         /// <summary>
         /// 物品领用 审核 通过
         /// </summary>
         /// <param name="id"></param>
         /// <param name="currUserId"></param>
         /// <returns></returns>
-        public async Task<JsonView> GoodsReceiveApproveAsync(int id,int currUserId)
+        public async Task<JsonView> GoodsReceiveApproveAsync(int id, int currUserId)
         {
             var appId = id;
 
             //验证审核流程
-            var flow = await _approvalProcessRep.GetFlowByBusinessAsync(appId,1);
+            var flow = await _approvalProcessRep.GetFlowByBusinessAsync(appId, 1);
             if (flow == null)
             {
                 _jv.Msg = $"审核流程不存在";
@@ -3577,7 +3734,7 @@ FROM
                 isNodeComplete = nodeRecords.All(x => x.AuditResult == 1);
             }
 
-            if (isNodeComplete) 
+            if (isNodeComplete)
             {
                 // 查找下一个节点
                 var nextNode = (await _approvalProcessRep.GetTemplateNodesAsync(flow.TemplateId))
@@ -3600,11 +3757,12 @@ FROM
                         return _jv;
                     }
 
+                    // 扣除库存
                     var deductStatus = await DeductStockAsync(appId);
 
                     if (!deductStatus)
                     {
-                        _jv.Msg = $"库存扣除失败失败!";
+                        _jv.Msg = $"库存扣除失败!";
                         _sqlSugar.RollbackTran();
                         return _jv;
                     }
@@ -3614,6 +3772,15 @@ FROM
                     // 进入下一个节点
                     flow.CurrentNodeId = nextNode.Id;
 
+                    // 更新业务状态为审核中
+                    var auditStatus = await UpdateStatusAsync(appId, GoodsAuditEnum.OutConfirming);
+                    if (!auditStatus)
+                    {
+                        _jv.Msg = $"审核状态更新失败!";
+                        _sqlSugar.RollbackTran();
+                        return _jv;
+                    }
+
                     // 为下一个节点创建审核记录
                     var nextNodeUsers = await _approvalProcessRep.GetTemplateNodeUsersAsync(nextNode.Id);
                     var records = nextNodeUsers.Select(user => new Sys_AuditRecord
@@ -3843,15 +4010,15 @@ FROM
                 if (goodsInfo == null) return false;
 
                 //1、物品库存扣除
-                var receiveQuantity = item.Quantity;
-                goodsInfo.StockQuantity -= receiveQuantity;
-                goodsInfo.OQ_Total += receiveQuantity;
+                goodsInfo.StockQuantity -= item.Quantity;
+                goodsInfo.OQ_Total += item.Quantity;
 
                 //2、入库批次关联领用人 更改批次库存
                 var goodsStorages = await _sqlSugar
                     .Queryable<Pm_GoodsStorage>()
                     .Where(x => x.IsDel == 0 &&
-                                x.GoodsId == receiveInfo.GoodsId &&
+                                x.GoodsId == item.GoodsId &&
+                                x.ConfirmStatus == GoodsConfirmEnum.Confirmed &&
                                 (x.Quantity - x.ReceiveQuantity) > 0
                         )
                     .OrderBy(x => x.CreateTime)
@@ -3859,18 +4026,20 @@ FROM
 
                 var goodsReceiveInfos = new List<GoodsReceiveLinkStorageView>();
                 var batchStorageInfos = new List<Pm_GoodsStorage>();
+
+                var receiveQuantity = 0.00M; //领用总数量
                 foreach (var storage in goodsStorages)
                 {
-                    if (receiveInfo.Quantity == receiveQuantity) break;
+                    if (item.Quantity == receiveQuantity) break;
 
                     var thisBatchSurplusQuantity = storage.Quantity - storage.ReceiveQuantity;
                     if (thisBatchSurplusQuantity <= 0.00M) continue;
 
                     var thisBatchReceiveQuantity = 0.00M; //此批次领用数量
                     const decimal unit = 0.50M;
-                    while (receiveQuantity < receiveInfo.Quantity)
+                    while (receiveQuantity < storage.Quantity)
                     {
-                        if (thisBatchSurplusQuantity == thisBatchReceiveQuantity) break;
+                        if (thisBatchSurplusQuantity == thisBatchReceiveQuantity || receiveQuantity == item.Quantity) break;
 
                         thisBatchReceiveQuantity += unit;
                         receiveQuantity += unit;

+ 77 - 45
OASystem/OASystem.Infrastructure/Repositories/Resource/OfficialActivitiesRepository.cs

@@ -1,6 +1,7 @@
 using AutoMapper;
 using MathNet.Numerics.Distributions;
 using MathNet.Numerics.Statistics.Mcmc;
+using NetTaste;
 using Newtonsoft.Json;
 using NPOI.SS.Formula.Functions;
 using OASystem.Domain;
@@ -13,6 +14,7 @@ using OASystem.Infrastructure.Tools;
 using System;
 using System.Collections.Generic;
 using System.Linq;
+using System.Reflection;
 using System.Text;
 using System.Threading.Tasks;
 
@@ -196,7 +198,6 @@ FROM
         public async Task<Result> OpOfficialActivities(OpOfficialActivitiesDto dto)
         {
             var result = new Result() { Code = -2, Msg = "未知错误" };
-
             var language = dto?.TranslatorInfo?.Language;
 
             #region 特殊字符转码  037 - 4.28 15:17
@@ -213,29 +214,61 @@ FROM
             _sqlSugar.BeginTran();
 
             //添加到资料库
-            var res_InvitationData = new Res_InvitationOfficialActivityData();
-            res_InvitationData.Country = dto.Country;
-            res_InvitationData.City = dto.Area;
-            res_InvitationData.UnitName = dto.Client;
-            res_InvitationData.Delegation = dto.DiId.ToString();
-            res_InvitationData.Address = dto.Address;
-            res_InvitationData.CreateUserId = dto.CreateUserId;
-            res_InvitationData.Contact = dto.Contact;
-            res_InvitationData.Job = dto.Job;
-            res_InvitationData.Tel = dto.Tel;
-            res_InvitationData.Field = dto.Field;
+            var res_InvitationData = new Res_InvitationOfficialActivityData
+            {
+                Country = dto.Country,
+                City = dto.Area,
+                UnitName = dto.Client,
+                Delegation = dto.DiId.ToString(),
+                Address = dto.Address,
+                CreateUserId = dto.CreateUserId,
+                Contact = dto.Contact,
+                Job = dto.Job,
+                Tel = dto.Tel,
+                Field = dto.Field
+            };
             EncryptionProcessor.EncryptProperties(res_InvitationData);
 
-            var isInserTranslator = false;
-            var translatorInfo = new Res_TranslatorLibrary();
-            if (true)
+            var isInserTranslator = true;
+
+            /*
+             * 2025-04-28 
+             * 翻译人员ID = 0 && 相关文本值 == “-” 不执行添加
+             *
+             */
+            // 获取所有string类型的公共实例属性 排除币种名称
+
+            var pTypes = new List<string>
+            {
+                "CurrencyName",
+            };
+            var stringProperties = dto.TranslatorInfo.GetType()
+                .GetProperties(BindingFlags.Public | BindingFlags.Instance)
+                .Where(p => p.PropertyType == typeof(string) && !pTypes.Contains(p.Name));
+
+            // 检查是否有任何属性的值为 -
+            int valCount = 0;
+            foreach (var property in stringProperties)
+            {
+                var value = (string)property.GetValue(dto.TranslatorInfo) ?? "";
+                if (value.Trim().Equals("-")) { valCount++; }
+            }
+
+            if (stringProperties.Count() == valCount) isInserTranslator = false;
+
+            var transInfo = new Res_TranslatorLibrary();
+
+            if (isInserTranslator)
             {
                 //翻译人员资料
-                translatorInfo = _mapper.Map<Res_TranslatorLibrary>(dto.TranslatorInfo);
-                translatorInfo.CreateUserId = dto.CreateUserId;
-                if (dto.TranslatorIdItem.Any()) translatorInfo.Id = dto.TranslatorIdItem[0];
+                transInfo = _mapper.Map<Res_TranslatorLibrary>(dto.TranslatorInfo);
 
-                EncryptionProcessor.EncryptProperties(translatorInfo);
+                transInfo.LastUpdateUserId = dto.CreateUserId;
+                transInfo.LastUpdateTime = DateTime.Now;
+                transInfo.CreateUserId = dto.CreateUserId;
+                if (dto.TranslatorIdItem.Any()) transInfo.Id = dto.TranslatorIdItem[0];
+
+                EncryptionProcessor.EncryptProperties(transInfo);
                 isInserTranslator = true;
             }
 
@@ -255,13 +288,13 @@ FROM
                 }
                 else
                 {
-                    var translatorId = translatorInfo.Id;
+                    var translatorId = transInfo.Id;
 
                     if (isInserTranslator)
                     {
                         if (translatorId > 0) // 翻译人员资料更新
                         {
-                            var tiStatus = await _sqlSugar.Updateable<Res_TranslatorLibrary>(translatorInfo)
+                            var tiStatus = await _sqlSugar.Updateable<Res_TranslatorLibrary>(transInfo)
                                 .UpdateColumns(x => new
                                 {
                                     x.Area,
@@ -285,7 +318,7 @@ FROM
                         }
                         else //添加翻译人员资料
                         {
-                            translatorId = await _sqlSugar.Insertable(translatorInfo).ExecuteReturnIdentityAsync();
+                            translatorId = await _sqlSugar.Insertable(transInfo).ExecuteReturnIdentityAsync();
                             if (translatorId == 0)
                             {
                                 _sqlSugar.RollbackTran();
@@ -345,21 +378,21 @@ FROM
                 {
                     DataID = res_InvitationData.Id;
                     //商邀资料
-                    await _sqlSugar.Updateable<Res_InvitationOfficialActivityData>(res_InvitationData)
-                                    .UpdateColumns(x => new
-                                    {
-                                        x.Country,
-                                        x.City,
-                                        x.UnitName,
-                                        x.Delegation,
-                                        x.Address,
-                                        x.CreateUserId,
-                                        x.Contact,
-                                        x.Job,
-                                        x.Tel,
-                                        x.Field,
-                                    })
-                                    .ExecuteCommandAsync();
+                    await _sqlSugar.Updateable(res_InvitationData)
+                        .UpdateColumns(x => new
+                        {
+                            x.Country,
+                            x.City,
+                            x.UnitName,
+                            x.Delegation,
+                            x.Address,
+                            x.CreateUserId,
+                            x.Contact,
+                            x.Job,
+                            x.Tel,
+                            x.Field,
+                        })
+                        .ExecuteCommandAsync();
                 }
                
                 //公务出访
@@ -401,9 +434,9 @@ FROM
                     {
                         #region 更新(公务信息关联翻译人员) 关联信息
 
-                        if (translatorInfo.Id > 0) //资料更新
+                        if (transInfo.Id > 0) //资料更新
                         {
-                            var tiStatus = await _sqlSugar.Updateable<Res_TranslatorLibrary>(translatorInfo)
+                            var tiStatus = await _sqlSugar.Updateable<Res_TranslatorLibrary>(transInfo)
                                 .UpdateColumns(x => new
                                 {
                                     x.Area,
@@ -426,13 +459,13 @@ FROM
                             }
 
                             var dutyLink_select = await _sqlSugar.Queryable<Grp_OfficialDutyLinkTranslator>()
-                           .Where(x => x.IsDel == 0 && x.OfficialDutyId == dto.Id && x.TranslatorId == translatorInfo.Id)
+                           .Where(x => x.IsDel == 0 && x.OfficialDutyId == dto.Id && x.TranslatorId == transInfo.Id)
                            .FirstAsync();
                             if (dutyLink_select == null)
                             {
                                 var odltStatus = await _sqlSugar.Insertable(new Grp_OfficialDutyLinkTranslator()
                                 {
-                                    TranslatorId = translatorInfo.Id,
+                                    TranslatorId = transInfo.Id,
                                     OfficialDutyId = dto.Id,
                                     CreateUserId = dto.CreateUserId,
                                     Remark = $"公务出访客户资料-->添加"
@@ -446,15 +479,15 @@ FROM
                         }
                         else // 添加
                         {
-                            translatorInfo.Id = await _sqlSugar.Insertable(translatorInfo).ExecuteReturnIdentityAsync();
-                            if (translatorInfo.Id == 0)
+                            transInfo.Id = await _sqlSugar.Insertable(transInfo).ExecuteReturnIdentityAsync();
+                            if (transInfo.Id == 0)
                             {
                                 _sqlSugar.RollbackTran();
                                 return new Result() { Code = -1, Msg = "翻译人员资料添加失败!", Data = new { Id = dto.Id } };
                             }
                             var odltStatus = await _sqlSugar.Insertable(new Grp_OfficialDutyLinkTranslator()
                             {
-                                TranslatorId = translatorInfo.Id,
+                                TranslatorId = transInfo.Id,
                                 OfficialDutyId = dto.Id,
                                 CreateUserId = dto.CreateUserId,
                                 Remark = $"公务出访客户资料-->添加"
@@ -468,7 +501,6 @@ FROM
                         #endregion
                     }
 
-
                     _sqlSugar.CommitTran();
                     result = new Result() { Code = 0, Msg = "修改成功!", Data = new { Id = dto.Id } };
                 }

+ 24 - 0
OASystem/OASystem.Infrastructure/Repositories/System/ApprovalProcessRepository.cs

@@ -156,5 +156,29 @@ namespace OASystem.Infrastructure.Repositories.System
                 .Where(x => x.NodeId == nodeId)
                 .ToListAsync();
         }
+
+        /// <summary>
+        /// 审核、重复操作权限验证
+        /// </summary>
+        /// <param name="tempId">模板Id</param>
+        /// <param name="busTypeId">业务类型</param>
+        /// <param name="busDataId">业务类型Id</param>
+        /// <param name="userId">用户Id</param>
+        /// <returns></returns>
+        public async Task<bool> VerifyAuditAuthAsync(int tempId,int busTypeId,int busDataId,int userId)
+        {
+            if (tempId < 1 || busTypeId < 1 || busDataId < 1) return false;
+
+            var flow = await _sqlSugar.Queryable<Sys_AuditFlow>().FirstAsync(x => x.IsDel == 0 && x.BusinessType == busTypeId && x.TemplateId == tempId && x.BusinessId == busDataId);
+            if (flow == null) return false;
+            if (flow.Status == 2 || flow.Status == 3) return false;
+
+            var node = await _sqlSugar.Queryable<Sys_AuditTemplateNode>()
+                .FirstAsync(x => x.IsDel == 0 && x.TemplateId == tempId && x.Id == flow.CurrentNodeId);
+            if (node == null) return false;
+
+            return await _sqlSugar.Queryable<Sys_AuditTemplateNodeUser>().AnyAsync(x => x.IsDel == 0 && x.NodeId == node.Id && x.UserId == userId);
+        }
+
     }
 }

+ 37 - 1
OASystem/OASystem.Infrastructure/Tools/CommonFun.cs

@@ -1,4 +1,5 @@
-using Newtonsoft.Json;
+using MathNet.Numerics.Statistics;
+using Newtonsoft.Json;
 using Newtonsoft.Json.Linq;
 using OASystem.Domain.ViewModels.Groups;
 using System.Collections;
@@ -145,6 +146,41 @@ public static class CommonFun
 
         return new string(fileName.Where(c => !invalidChars.Contains(c)).ToArray());
     }
+
+    /// <summary>
+    /// 文件后缀名签名
+    /// </summary>
+    public static Dictionary<string, List<byte[]>> FileSignature => new Dictionary<string, List<byte[]>>
+        {
+            { ".jpeg", new List<byte[]>
+                {
+                    new byte[] { 0xFF, 0xD8, 0xFF, 0xE0 },
+                    new byte[] { 0xFF, 0xD8, 0xFF, 0xE2 },
+                    new byte[] { 0xFF, 0xD8, 0xFF, 0xE3 },
+                }
+            },
+            { ".png", new List<byte[]>
+                {
+                    new byte[] { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A }
+                }
+            },
+            { ".pdf", new List<byte[]>
+                {
+                    new byte[] { 0x25, 0x50, 0x44, 0x46 }
+                }
+            },
+            { ".xls", new List<byte[]>
+                { 
+                    new byte[] { 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1 } 
+                } 
+            },
+            { ".xlsx", new List<byte[]> 
+                { 
+                    new byte[] { 0x50, 0x4B, 0x03, 0x04 } 
+                } 
+            }
+        };
+
     #endregion
 
     #region IP