Browse Source

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

yuanrf 2 days ago
parent
commit
6f6eba8403

+ 6 - 1
OASystem/OASystem.Api/Controllers/FinancialController.cs

@@ -2177,6 +2177,7 @@ namespace OASystem.API.Controllers
         public async Task<IActionResult> PostPayRequest_Center(PostPayRequestByDateRangeDto dto)
         {
             Stopwatch stopwatch = Stopwatch.StartNew();
+
             #region 验证
             DateTime beginDt, endDt;
             string format = "yyyy-MM-dd";
@@ -2198,6 +2199,7 @@ namespace OASystem.API.Controllers
             #endregion
 
             #endregion
+
             try
             {
                 PaymentRequestCheckedView checkedView = new PaymentRequestCheckedView();
@@ -2648,7 +2650,10 @@ namespace OASystem.API.Controllers
                                                 From Fin_DailyFeePayment dfp
                                                 Inner Join Sys_Company c On dfp.CompanyId = c.Id
                                                 Left Join Sys_Users u On dfp.CreateUserId = u.Id
-                                                Where dfp.IsDel=0 {0} And dfp.FAudit = 1 And dfp.MAudit = 1 And dfp.IsPay = 0
+                                                Where dfp.IsDel=0 {0} 
+                                                AND (dfp.FAudit = 1 OR dfp.FAudit = 3) 
+                                                AND (dfp.MAudit = 1 OR dfp.MAudit = 3) 
+                                                AND dfp.IsPay = 0
                                                 ) temp ", sqlWhere);
             #endregion
 

+ 265 - 51
OASystem/OASystem.Api/Controllers/GroupsController.cs

@@ -1768,7 +1768,7 @@ FROM
     SELECT
       ROW_NUMBER() OVER(
         ORDER BY
-          gdi.CreateTime Desc
+          gdi.VisitDate Desc
       ) AS ROW_NUMBER,
       gdi.Id,
       SalesQuoteNo,
@@ -1798,7 +1798,7 @@ FROM
     WHERE
       gdi.IsDel = 0
       AND gdi.IsBid = 0
-      AND gdi.CreateTime BETWEEN '{0}' AND '{1}'
+      AND gdi.VisitDate BETWEEN '{0}' AND '{1}'
   ) temp", _beginDt.ToString("yyyy-MM-dd HH:mm:ss"), _endDt.ToString("yyyy-MM-dd HH:mm:ss"));
 
 
@@ -13219,7 +13219,7 @@ FROM
         /// <returns></returns>
         [HttpPost]
         [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
-        public async Task<IActionResult> EnterExitCostQuoteNameListDto(EnterExitCostQuoteNameListDto dto)
+        public async Task<IActionResult> EnterExitCostQuoteNameList(EnterExitCostQuoteNameListDto dto)
         {
             return Ok(await _enterExitCostQuoteRep.QuoteNameListAsync(dto));
         }
@@ -13230,7 +13230,7 @@ FROM
         /// <returns></returns>
         [HttpPost]
         [ProducesResponseType(typeof(JsonView), StatusCodes.Status200OK)]
-        public async Task<IActionResult> EnterExitCostQuoteGroupNameListDto(EnterExitCostQuoteGroupNameListDto dto)
+        public async Task<IActionResult> EnterExitCostQuoteGroupNameList(EnterExitCostQuoteGroupNameListDto dto)
         {
             return Ok(await _enterExitCostQuoteRep.GroupNameListAsync(dto));
         }
@@ -13248,8 +13248,54 @@ FROM
             if (groupId < 1) return Ok(JsonView(false, "请传入有效的GroupId;"));
             if (currUserId < 1) return Ok(JsonView(false, "请传入有效的CurrUserId;"));
 
+            //验证报价数据是否存在
+            var isNull = await _sqlSugar.Queryable<Grp_EnterExitCostQuote>().FirstAsync(x => x.IsDel == 0 && x.GroupId == dto.DiId);
+            if (isNull != null)
+            {
+                var info1 = await _enterExitCostQuoteRep.InfoAsync(new EnterExitCostQuoteInfoDto() { Id = isNull.Id });
+
+                if (!info1.Rates.Any())
+                {
+                    var rates = await GeneralMethod.EnterExitCostInitRate();
+                    rates.Insert(0, new CurrencyInfo() { CurrencyCode = "CNY", CurrencyName = "人民币", Rate = 1.00000M });
+                    info1.Rates = rates.ToArray();
+                }
+                return Ok(JsonView(info1));
+            }
+
+            var result = await _enterExitCostQuoteRep.InfoByGroupIdAsync(dto.DiId);
+
+            result.GroupId = groupId;
+            //处理报价名称
+            var groupInfo = await _sqlSugar.Queryable<Grp_DelegationInfo>().FirstAsync(x => x.Id == dto.DiId && x.IsDel == 0);
+            if (groupInfo != null)
+            {
+                var visitCountry = groupInfo.VisitCountry;
+                if (!string.IsNullOrEmpty(visitCountry))
+                {
+                    string quoteName = string.Empty;
+                    if (visitCountry.Contains("|"))
+                    {
+                        var countrys = visitCountry.Split("|");
+                        quoteName = string.Join("、", countrys);
+                    }
+                    else quoteName = visitCountry;
+
+                    quoteName += $"团组报价表";
+                    result.Name = quoteName;
+                }
+            }
+
             var info = await _enterExitCostRep.GetEnterExitCostInfoByDiId(dto);
-            if (info.Code != StatusCodes.Status200OK) return Ok(info);
+            if (info.Code != StatusCodes.Status200OK)
+            {
+                if (!result.Rates.Any())
+                {
+                    var rates = await GeneralMethod.EnterExitCostInitRate();
+                    result.Rates = rates.ToArray();
+                }
+                return Ok(JsonView(true, $"出入境费用明细未填写!", result));
+            }
 
             var infoView = info.Data as EnterExitCostInfoView;
             if (infoView == null) return Ok(JsonView(false, "数据类型转换失败!;"));
@@ -13258,8 +13304,14 @@ FROM
             var cityFilter = new List<string>() { "全部城市", "其他城市" };
             var currencys = await _sqlSugar.Queryable<Sys_SetData>().Where(x => x.IsDel == 0 && x.STid == 66).ToListAsync();
             var eecRates = infoView.Currencys;
-             
-            var groupInfo = await _sqlSugar.Queryable<Grp_DelegationInfo>().FirstAsync(x => x.Id == dto.DiId && x.IsDel == 0);
+            //默认添加人名币
+            if (!eecRates.Any(x => x.CurrencyCode.Equals("CNY")))
+            {
+                eecRates.Insert(0, new CurrencyInfo() { CurrencyCode = "CNY", CurrencyName = "人民币", Rate = 1.00000M });
+            }
+
+
+            //处理团组人数
             int pplNum = 1;
             if (groupInfo != null) pplNum = groupInfo.VisitPNumber;
 
@@ -13465,7 +13517,7 @@ FROM
                     var thisRate = eecRates.FirstOrDefault(x => x.CurrencyCode.Equals(thisCurrency))?.Rate ?? 1.0000M;
                     int quantity = item.ToList().Count;
 
-                    mealCosts.Add(new QuoteSubItemInfo
+                    miscCosts.Add(new QuoteSubItemInfo
                     {
                         ItemId = miscItemTypeId,
                         Index = miscIndex,
@@ -13480,7 +13532,7 @@ FROM
                     miscIndex++;
                 }
 
-                views.AddRange(mealCosts);
+                views.AddRange(miscCosts);
             }
 
             #endregion
@@ -13546,9 +13598,6 @@ FROM
 
             #endregion
 
-            var result = await _enterExitCostQuoteRep.InfoAsync(new EnterExitCostQuoteInfoDto() { });
-
-            result.Rates = eecRates.ToArray();
             if (result.FeeItems.Any())
             {
                 result.FeeItems.Select(x =>
@@ -13557,11 +13606,22 @@ FROM
                             if (feeInfos.Any()) x.Infos = feeInfos;
                             return x;
                         }
-                    )
-                    .OrderBy(x => x.Index)
+                    ).OrderBy(x => x.Index)
                     .ToList();
+
+                if (!result.Rates.Any())
+                {
+                    if (eecRates.Any()) result.Rates = eecRates?.ToArray() ?? Array.Empty<CurrencyInfo>();
+                    else
+                    {
+                        var rates = await GeneralMethod.EnterExitCostInitRate();
+                        rates.Insert(0,new CurrencyInfo() { CurrencyCode = "CNY", CurrencyName = "人民币", Rate = 1.00000M });
+                        result.Rates = rates.ToArray();
+                    }
+                }
             }
 
+
             return Ok(JsonView(result));
         }
 
@@ -13578,6 +13638,7 @@ FROM
             if (!info.Rates.Any())
             {
                 var rates = await GeneralMethod.EnterExitCostInitRate();
+                rates.Add(new CurrencyInfo() { CurrencyCode = "CNY", CurrencyName = "人民币", Rate = 1.00000M });
                 info.Rates = rates.ToArray();
             }
 
@@ -13620,7 +13681,6 @@ FROM
             if (dto.Id < 1) return Ok(JsonView(false, MsgTips.Id));
             if (dto.CurrUserId < 1) return Ok(JsonView(false, MsgTips.UserId));
 
-
             var info = await _enterExitCostQuoteRep.InfoAsync(new EnterExitCostQuoteInfoDto() { Id = dto.Id });
             if (info == null) return Ok(JsonView(false, "报价信息未填写!"));
 
@@ -13631,12 +13691,12 @@ FROM
             var vehArranges = info.FeeItems.FirstOrDefault(x => x.ItemId == 1357);   //车辆安排
             var inviteTo = info.FeeItems.FirstOrDefault(x => x.ItemId == 1358);      //邀请函发放对象
             var inviteCosts = info.FeeItems.FirstOrDefault(x => x.ItemId == 1359);   //邀请函费用
-            var inviteTime = info.FeeItems.FirstOrDefault(x => x.ItemId == 1560);    //邀请函发放时间
-            var officialActs = info.FeeItems.FirstOrDefault(x => x.ItemId == 1561);  //公务活动
-            var visaIns = info.FeeItems.FirstOrDefault(x => x.ItemId == 1562);       //签证+保险
-            var serviceCosts = info.FeeItems.FirstOrDefault(x => x.ItemId == 1563);  //服务费
-            var pubMiscs = info.FeeItems.FirstOrDefault(x => x.ItemId == 1564);      //公杂费
-            var taxCosts = info.FeeItems.FirstOrDefault(x => x.ItemId == 1565);      //税费
+            var inviteTime = info.FeeItems.FirstOrDefault(x => x.ItemId == 1360);    //邀请函发放时间
+            var officialActs = info.FeeItems.FirstOrDefault(x => x.ItemId == 1361);  //公务活动
+            var visaIns = info.FeeItems.FirstOrDefault(x => x.ItemId == 1362);       //签证+保险
+            var serviceCosts = info.FeeItems.FirstOrDefault(x => x.ItemId == 1363);  //服务费
+            var pubMiscs = info.FeeItems.FirstOrDefault(x => x.ItemId == 1364);      //公杂费
+            var taxCosts = info.FeeItems.FirstOrDefault(x => x.ItemId == 1365);      //税费
 
             //获取模板
             string tempPath = AppSettingsHelper.Get("ExcelBasePath") + "Template/出入境费用明细报价表模板.xlsx";
@@ -13648,8 +13708,8 @@ FROM
             designer.SetDataSource("CompanyLabel", "");
 
             #region 国际旅费
-            designer.SetDataSource("IntTravelTitle", intTravelCosts.ItemName);
-            if (intTravelCosts.Infos.Any())
+            designer.SetDataSource("IntTravelTitle", intTravelCosts?.ItemWrapName ?? "国际旅费\r\n(公务舱和经济舱分别罗列)");
+            if (intTravelCosts != null && intTravelCosts.Infos.Any())
             {
                 var cabClassFilter = new string[] { "经济舱", "公务舱", "头等舱" };
 
@@ -13683,46 +13743,47 @@ FROM
                 designer.SetDataSource("IntTravelLabel", label.ToString());
             }
             #endregion
+
             #region 住宿费 
-            designer.SetDataSource("AccomTitle", accomCosts.ItemName);
-            if (accomCosts.Infos.Any())
+            designer.SetDataSource("AccomTitle", accomCosts?.ItemWrapName ?? "住宿费\r\n(请备注明酒店星级)");
+            if (accomCosts!=null && accomCosts.Infos.Any())
             {
-                string currencyName = string.Empty;
+                string currencyName = string.Empty,
+                       countryName = string.Empty;
                 decimal rate = 1.0000M;
 
                 StringBuilder label = new StringBuilder();
                 label.AppendLine("全程五星酒店,每人1间房");
                 foreach (var item in accomCosts.Infos)
                 {
-                    string hotelName = string.Empty;
+                    //乌兹别克斯坦: 塔什干:120美金/间/晚*2*6人
+                    string name = string.Empty, thisCountryName = string.Empty;
                     if (item.FeeName.Contains("-"))
                     {
                         var feeName = item.FeeName.Split('-');
-                        hotelName = $"\r\n{feeName[0]}:\r\n{feeName[1]}:";
+                        thisCountryName = feeName[0];
+                        if (!thisCountryName.Equals(countryName)) countryName = feeName[0];
+
+                        name = feeName[1];
                     }
-                    else hotelName = $"\r\n{item.FeeName}:";
+                    else name = item.FeeName;
+                    string thisFeeName = string.Empty;
+                    if (!thisCountryName.Equals(countryName)) thisFeeName = $"{countryName}:\r\n{name}:";
+                    else thisFeeName = $"\r\n{name}:";
 
                     var rateInfo = rates.FirstOrDefault(x => item.Currency.Equals(x.CurrencyCode));
                     currencyName = rateInfo?.CurrencyName ?? "UnKnow";
                     rate = rateInfo?.Rate ?? 1.0000M;
 
-                    label.Append(hotelName);
-                    label.Append(item.UnitPrice.TruncDecimals(2));
-                    label.Append(currencyName);
-                    label.Append("/间/晚*");
-                    label.Append(item.Quantity.ToString("#0"));
-                    label.AppendLine("人");
+                    string subLabel = string.Format("{0}{1}{2}/间/晚*{3}*{4}人", thisFeeName, item.UnitPrice.TruncDecimals(2), currencyName, item.Quantity.ToString("#0"), item.PplNum.ToString("#0"));
+                    label.AppendLine(subLabel);
 
                 }
                 if (label.HasValue())
                 {
-                    label.Append("\r\n以上小计:");
-                    label.Append(accomCosts.TotalAmt.TruncDecimals(2));
-                    label.Append("元(");
-                    label.Append(currencyName);
-                    label.Append("汇率:");
-                    label.Append(rate.TruncDecimals(4));
-                    label.Append(")");
+                    //以上小计:52440元(美金汇率:7.5  )
+                    string subLabel = string.Format("\r\n以上小计:{0}元({1}汇率:{2})", accomCosts.TotalAmt.TruncDecimals(2), currencyName, rate.TruncDecimals(4));
+                    label.AppendLine(subLabel);
                 }
 
                 designer.SetDataSource("AccomLabel", label.ToString());
@@ -13730,8 +13791,8 @@ FROM
             #endregion
 
             #region 餐饮费 
-            designer.SetDataSource("MealTitle", mealCosts.ItemName);
-            if (mealCosts.Infos.Any())
+            designer.SetDataSource("MealTitle", mealCosts?.ItemWrapName ?? "餐饮费");
+            if (mealCosts != null && mealCosts.Infos.Any())
             {
                 string currencyName = string.Empty;
                 decimal rate = 1.0000M;
@@ -13777,21 +13838,18 @@ FROM
             #endregion
 
             #region 车辆安排 
-            designer.SetDataSource("VehArrangeTitle", vehArranges.ItemName);
-            if (vehArranges.Infos.Any())
+            designer.SetDataSource("VehArrangeTitle", vehArranges?.ItemWrapName ?? "车辆安排\r\n(司兼导分开的情况下,车辆品牌、座位及费用)");
+            if (vehArranges!=null&&vehArranges.Infos.Any())
             {
                 string currencyName = string.Empty;
                 //decimal rate = 1.0000M;
                 StringBuilder label = new StringBuilder();
                 foreach (var item in vehArranges.Infos)
                 {
-                    label.Append(item.Remark);
                     label.AppendLine();
                     label.AppendLine();
                     label.Append(item.FeeName);
-                    label.Append("\r\n\r\n费用:");
-                    label.Append(item.FeeName);
-                    label.Append(item.TotalAmt.TruncDecimals(2));
+                    label.Append($"\r\n\r\n费用:{item.TotalAmt.TruncDecimals(2)}元");
                 }
 
                 designer.SetDataSource("VehArrangeLabel", label.ToString());
@@ -13799,9 +13857,165 @@ FROM
             #endregion
 
             #region 邀请函发放对象
-            designer.SetDataSource("InviteToTitle", inviteTo.ItemName);
+            designer.SetDataSource("InviteToTitle", inviteTo?.ItemWrapName ?? "邀请函发放对象");
+            designer.SetDataSource("InviteToContent", "");
+            #endregion
+
+            #region 邀请函费
+            designer.SetDataSource("InviteCostTitle", inviteCosts?.ItemWrapName ?? "邀请函费用");
+            StringBuilder is_label = new StringBuilder();
+            if (inviteCosts != null&&inviteCosts.Infos.Any())
+            {
+                string currencyName = string.Empty;
+                decimal rate = 1.0000M;
+                foreach (var item in inviteCosts.Infos)
+                {
+                    //乌兹别克斯坦:2000美金
+                    currencyName = item.Currency;
+                    rate = rates.FirstOrDefault(x => currencyName.Equals(x.CurrencyCode))?.Rate ?? 1.0000M;
+                    string label = string.Format("{0}:{1}{2}", item.FeeName, item.UnitPrice.TruncDecimals(2), currencyName);
+                    is_label.AppendLine(label);
+                }
+
+                if (is_label.HasValue())
+                {
+                    //以上小计:28500元(美金汇率:7.5)
+                    string label = string.Format("以上小计:{0}{1}({2}汇率:{3})", inviteCosts.TotalAmt.TruncDecimals(2),"元", currencyName, rate.TruncDecimals(4));
+                    is_label.AppendLine(label);
+                }
+            }
+            designer.SetDataSource("InviteCostContent", is_label.ToString());
+            #endregion
+
+            #region 邀请函发放时间
+            designer.SetDataSource("InviteToTimeTitle", inviteTime?.ItemWrapName ?? "邀请函发放时间");
+            designer.SetDataSource("InviteToTimeContent", "拿到团员名单10-15工作日");
+            #endregion
+
+            #region 公务活动(含翻译)
+            designer.SetDataSource("OfficialActsTitle", officialActs?.ItemWrapName ?? "公务活动(含翻译)");
+
+            StringBuilder oa_label = new StringBuilder();
+            if (officialActs != null && officialActs.Infos.Any())
+            {
+                string currencyName = string.Empty;
+                decimal rate = 1.0000M;
+                string label_title = string.Empty, label_content = "超出报价部分需额付费:\r\n";
+                foreach (var item in officialActs.Infos)
+                {
+                    //乌兹别克斯坦:1000美金/场
+                    currencyName = item.Currency;
+                    rate = rates.FirstOrDefault(x => currencyName.Equals(x.CurrencyCode))?.Rate ?? 1.0000M;
+                    string label_remark = string.Empty;
+                    if (!string.IsNullOrEmpty(item.Remark)) label_remark = $"({item.Remark})";
+                    label_content += string.Format("{0}:{1}{2}/场{3}\r\n", item.FeeName, item.UnitPrice.TruncDecimals(2), currencyName, label_remark);
+                }
+                label_content += "*总费用中未含超出公务活动价格";
+
+                //8场公务活动(以上小计:60000元)
+                var quantity = officialActs.Infos.Sum(x => x.Quantity);
+                label_title = string.Format("{0}场公务活动(以上小计:{1}元)", quantity, officialActs.TotalAmt.TruncDecimals(2));
+                oa_label.AppendLine(label_title);
+                oa_label.AppendLine(label_content);
+            }
+            designer.SetDataSource("OfficialActsContent", oa_label.ToString());
+            #endregion
+
+            #region 签证+保险
+            designer.SetDataSource("VisaInsTitle", visaIns?.ItemWrapName ?? "签证+保险\r\n(单位:元)");
+
+            StringBuilder vi_label = new StringBuilder();
+            if (visaIns  != null &&  visaIns.Infos.Any())
+            {
+                foreach (var item in visaIns.Infos)
+                {
+                    //签证:500元/人
+                    string label = string.Format("{0}:{1}元/人*{2}人", item.FeeName, item.UnitPrice.TruncDecimals(2), item.PplNum);
+                    vi_label.AppendLine(label);
+                }
+                if (vi_label.HasValue())
+                {
+                    //以上小计:6000元
+                    string label = string.Format("以上小计:{0}元", visaIns.TotalAmt.TruncDecimals(2));
+                    vi_label.AppendLine(label);
+                }
+
+            }
+
+            designer.SetDataSource("VisaInsContent", vi_label.ToString());
+            #endregion
+
+            #region 服务费
+            designer.SetDataSource("ServiceCostTitle", serviceCosts?.ItemWrapName ?? "服务费");
+            designer.SetDataSource("ServiceCostContent", serviceCosts?.TotalAmt.TruncDecimals(2) ?? 0.00M);
             #endregion
 
+            #region 公杂费
+            designer.SetDataSource("PubMiscsTitle", pubMiscs?.ItemWrapName ?? "公杂费\r\n(发给团组成员)");
+            StringBuilder pm_label = new StringBuilder();
+            if (pubMiscs != null && pubMiscs.Infos.Any())
+            {
+                string currencyName = string.Empty,
+                       countryName = string.Empty;
+                decimal rate = 1.0000M;
+                foreach (var item in pubMiscs.Infos)
+                {
+                    //乌兹别克斯坦:塔什干:32美金 / 天 * 3 * 6人
+                    string name = string.Empty, thisCountryName = string.Empty;
+                    if (item.FeeName.Contains("-"))
+                    {
+                        var feeName = item.FeeName.Split('-');
+                        thisCountryName = feeName[0];
+                        if (!thisCountryName.Equals(countryName)) countryName = feeName[0];
+
+                        name = feeName[1];
+                    }
+                    else name = item.FeeName;
+                    string thisFeeName = string.Empty;
+                    if (!thisCountryName.Equals(countryName)) thisFeeName = $"{countryName}:\r\n{name}:";
+                    else thisFeeName = $"\r\n{name}:";
+
+                    var rateInfo = rates.FirstOrDefault(x => item.Currency.Equals(x.CurrencyCode));
+                    currencyName = rateInfo?.CurrencyName ?? "UnKnow";
+                    rate = rateInfo?.Rate ?? 1.0000M;
+
+                    string label = string.Format("{0}:{1}{2}/天*{3}*{4}人", thisFeeName, item.UnitPrice.TruncDecimals(2), currencyName, item.Quantity, item.PplNum);
+                    pm_label.AppendLine(label);
+                }
+                if (pm_label.HasValue())
+                {
+                    //以上小计:13497.6元\r\n(美金汇率:7.5 )\r\n部分发放成员
+                    pm_label.AppendLine(string.Format("以上小计:{0}元", pubMiscs.TotalAmt.TruncDecimals(2)));
+                    pm_label.AppendLine(string.Format("({0}汇率:{1})", currencyName, rate.TruncDecimals(4)));
+                    pm_label.AppendLine(string.Format("部分发放成员"));
+                }
+
+            }
+            designer.SetDataSource("PubMiscsContent", pm_label.ToString());
+            #endregion
+
+            #region 税费
+            designer.SetDataSource("TaxCostTitle", taxCosts?.ItemWrapName ?? "税费");
+            designer.SetDataSource("TaxCostContent", taxCosts?.TotalAmt.TruncDecimals(2) ?? 0.00M);
+            #endregion
+
+            #region 合计(单位:元)
+            designer.SetDataSource("CostTotalTitle", "合计\r\n(单位:元)");
+            designer.SetDataSource("CostTotalContent", info.FeeItems.Sum(x => x.TotalAmt).TruncDecimals(2));
+            #endregion
+
+            #region 汇率 Remark
+            var rate_label = new StringBuilder();
+            var rateGroups = rates.GroupBy(x => x.CurrencyName);
+            foreach (var item in rateGroups)
+            {
+                //美元汇率按\r\n1:7.5
+                string label = string.Format("{0}汇率按\r\n1:{1}", item.Key, item.FirstOrDefault()?.Rate.TruncDecimals(4) ?? 0.0000M);
+                rate_label.AppendLine(label);
+            }
+
+            designer.SetDataSource("RateLabel", rate_label.ToString());
+            #endregion
 
             designer.Process();
 

+ 84 - 12
OASystem/OASystem.Api/Controllers/PersonnelModuleController.cs

@@ -1,5 +1,7 @@
 using Aspose.Cells;
+using EyeSoft.Reflection;
 using FluentValidation;
+using Microsoft.AspNetCore.Mvc.Infrastructure;
 using Microsoft.AspNetCore.SignalR;
 using NPOI.OpenXmlFormats.Dml.Chart;
 using OASystem.API.OAMethodLib;
@@ -15,6 +17,7 @@ using OASystem.Domain.Entities.PersonnelModule;
 using OASystem.Domain.ViewModels.JuHeExchangeRate;
 using OASystem.Domain.ViewModels.PersonnelModule;
 using OASystem.Domain.ViewModels.QiYeWeChat;
+using OASystem.Infrastructure.Repositories.Groups;
 using OASystem.Infrastructure.Repositories.PersonnelModule;
 using System.Collections;
 using System.Data;
@@ -42,7 +45,8 @@ namespace OASystem.API.Controllers
 
         private readonly IHubContext<ChatHub, IChatClient> _hubContext;
         private readonly GoodsRepository _goodsRep;
-        //private readonly GroupsController _groupsController;
+        private readonly DecreasePaymentsRepository _otherPaymentRep;
+        private readonly FeeAuditRepository _feeAuditRep;
 
         private string url;
         private string path;
@@ -58,7 +62,8 @@ namespace OASystem.API.Controllers
         /// <param name="hubContext"></param>
         /// <param name="goodsRep"></param>
         /// <param name="sqlSugar"></param>
-        ///// <param name="groupsController"></param>
+        /// <param name="otherPaymentRep"></param>
+        /// <param name="feeAuditRep"></param>
         public PersonnelModuleController(
             IHubContext<ChatHub, IChatClient> hubContext,
             IMapper mapper,
@@ -67,8 +72,9 @@ namespace OASystem.API.Controllers
             UsersRepository usersRep,
             TaskAllocationRepository taskAllocationRep,
             GoodsRepository goodsRep,
-            SqlSugarClient sqlSugar
-           // GroupsController groupsController
+            SqlSugarClient sqlSugar,
+            DecreasePaymentsRepository otherPaymentRep,
+            FeeAuditRepository feeAuditRep
             )
         {
             _mapper = mapper;
@@ -89,7 +95,8 @@ namespace OASystem.API.Controllers
             this._taskAllocationRep = taskAllocationRep;
             _hubContext = hubContext;
             _goodsRep = goodsRep;
-            //_groupsController = groupsController;
+            _otherPaymentRep = otherPaymentRep;
+            _feeAuditRep = feeAuditRep;
         }
 
         #region 工资表单
@@ -2158,12 +2165,13 @@ WHERE
                 })
                 .ToArray();
 
-
-            var view = await _goodsRep.GoodsReceiveAudit(idArray, currUserInfo.UserId, dto.AuditEnum);
-
+            //var view = await _goodsRep.GoodsReceiveAudit(idArray, currUserInfo.UserId, dto.AuditEnum);
+            var view = new JsonView() { Code = StatusCodes.Status200OK};
             //TODO:出库成功 并且是团组相关物资 向团组其他款项添加信息
             #region 出库成功并且是团组相关物资 向团组其他款项添加信息
 
+            if (view.Code != StatusCodes.Status200OK) return Ok(view);
+
             if (idArray.Length < 1) return Ok(view);
 
             int receiveId = idArray[0];
@@ -2171,7 +2179,8 @@ WHERE
             var receiveInfo = await _sqlSugar.Queryable<Pm_GoodsReceive>().FirstAsync(x => x.IsDel == 0 && x.Id == receiveId);
             if (receiveInfo == null) return Ok(view);
 
-            if (receiveInfo.AuditStatus != GoodsAuditEnum.OutConfirmed) return Ok(view);
+            var auditEnums = new List<GoodsAuditEnum>(){ GoodsAuditEnum.OutConfirmed , GoodsAuditEnum.OutRejected };
+            if (!auditEnums.Contains( receiveInfo.AuditStatus)) return Ok(view);
 
             var groupInfo = await _sqlSugar.Queryable<Grp_DelegationInfo>().FirstAsync(x => x.IsDel == 0 && x.Id == receiveInfo.GroupId);
             if (groupInfo == null) return Ok(view);
@@ -2183,15 +2192,78 @@ WHERE
             var basicInfo = basicData.FirstOrDefault(x => x.Name.Equals(goodsInfo.Name));
             if (basicInfo == null) return Ok(view);
 
-            var requestData = new DecreasePaymentsOpDto() {
+            string priceName = basicInfo.Name;
+
+            _ = decimal.TryParse(basicInfo.Remark, out decimal price);
+            decimal total = price * receiveInfo.Quantity;
+
+            var requestData = new DecreasePaymentsOpDto()
+            {
                 Status = 1,
                 DiId = groupInfo.Id,
+                PriceName = priceName,
+                Price = price,
+                Quantity = receiveInfo.Quantity,
+                FeeTotal = total,
+                Currency = 836,
+                FilePath = "",
+                OrbitalPrivateTransfer = 0,
+                OTAOrderNo = "-",
+                OtherBankName = "-",
+                OtherSideName = "-",
+                OtherSideNo = "-",
+                PayDId = 105,
+                SupplierAddress = "-",
+                SupplierArea = 1,
+                SupplierContact = "-",
+                SupplierContactNumber = "-",
+                SupplierEmail = "-",
+                SupplierName = "-",
+                SupplierSocialAccount = "-",
+                SupplierTypeId = 0,
+                CreateUserId = currUserInfo.UserId,
+                Remark = $"物资领用模块添加"
+            };
 
+            //其他费用
 
-            };
-            //var otherFeeView = await _groupsController.OpDecreasePayments(requestData);
+            #region 调用方法
+            JsonView groupData = await _otherPaymentRep.OpDecreasePayments(requestData);
+            if (groupData.Code != 200)
+            {
+                view.Msg += groupData.Msg;
+                return Ok(view);
+            }
 
+            #region 应用推送
+
+            int diId = requestData.DiId, status = requestData.Status;
+
+            int otherId = Convert.ToInt32(groupData.Data.GetType().GetProperty("dataId").GetValue(groupData.Data, null) ?? 0);
+            int ccpId = Convert.ToInt32(groupData.Data.GetType().GetProperty("ccpId").GetValue(groupData.Data, null) ?? 0);
+            int sign = Convert.ToInt32(groupData.Data.GetType().GetProperty("sign").GetValue(groupData.Data, null) ?? 0);
+
+            //自动审核
+            var autoAdit = await _feeAuditRep.FeeAutomaticAudit(3, diId, otherId);
+
+            await AppNoticeLibrary.SendChatMsg_GroupStatus_ApplyFee(ccpId, sign, QiyeWeChatEnum.GuoJiaoLeaderChat);
+
+            //2024-10-21 新增LZ UID
+            var userIds = new List<int>() { 208 };
+            //var userIds = new List<int>() { 21 };
+            string title = $"系统通知";
+            string content = "";
             
+            var ccpInfo = await _sqlSugar.Queryable<Grp_CreditCardPayment>().Where(x => x.Id == ccpId).FirstAsync();
+            if (status == 1) content = $"[新增-其他款项({groupInfo?.TeamName ?? "-"})]一项费用:{(ccpInfo.PayMoney * ccpInfo.DayRate).ToString("#0.00")} CNY;";
+            else if (status == 2) content = $"[更新-其他款项({groupInfo?.TeamName ?? "-"})]一项费用:{(ccpInfo.PayMoney * ccpInfo.DayRate).ToString("#0.00")} CNY;";
+
+            await GeneralMethod.MessageIssueAndNotification(MessageTypeEnum.GroupBusinessOperations, title, content, userIds, diId);
+
+            //await APNsTools.iOS_PushNotifications1("051", $"其他款项费用审核", "", content);
+
+            #endregion
+            #endregion
 
             #endregion
 

+ 2 - 2
OASystem/OASystem.Domain/Entities/Financial/Fin_DailyFeePayment.cs

@@ -26,7 +26,7 @@ namespace OASystem.Domain.Entities.Financial
 
         /// <summary>
         /// 总经理审核
-        /// 0 未审核 1 审核通过 2 审核未通过
+        /// 0 未审核 1 审核通过 2 审核未通过 3 自动审核
         /// </summary>
         [SugarColumn(IsNullable = true, ColumnDataType = "int")]
         public int MAudit { get; set; }
@@ -39,7 +39,7 @@ namespace OASystem.Domain.Entities.Financial
 
         /// <summary>
         /// 财务主管审核
-        /// 0 未审核 1 审核通过 2 审核未通过
+        /// 0 未审核 1 审核通过 2 审核未通过 3 自动审核
         /// </summary>
         [SugarColumn(IsNullable = true,ColumnDataType = "int")]
         public int FAudit { get; set; }

+ 2 - 2
OASystem/OASystem.Domain/Entities/PersonnelModule/Pm_GoodsReceive.cs

@@ -7,7 +7,6 @@ using System.Threading.Tasks;
 
 namespace OASystem.Domain.Entities.PersonnelModule
 {
-
     /// <summary>
     /// 物品领用表
     /// </summary>
@@ -70,7 +69,8 @@ namespace OASystem.Domain.Entities.PersonnelModule
         /// 领用/出库确认 状态描述
         /// </summary>
         [SugarColumn(ColumnDescription = "领用/出库确认 状态描述", IsNullable = true, ColumnDataType = "varchar(255)")]
-        public string StatusDesc { get; set; } = string.Format("领用确认:状态:待确认  审核人:-  审核时间:-;<br/>人事部:状态:待确认  审核人:-  审核时间:-;<br/>财务部:状态:待确认  审核人:-  审核时间:-;");
+        public string StatusDesc { get; set; }
+        // = string.Format("领用确认:状态:待确认  审核人:-  审核时间:-;<br/>人事部:状态:待确认  审核人:-  审核时间:-;<br/>财务部:状态:待确认  审核人:-  审核时间:-;");
 
     }
 }

+ 9 - 4
OASystem/OASystem.Domain/Enums/GoodsAuditEnum.cs

@@ -13,7 +13,7 @@ namespace OASystem.Domain.Enums
     public enum GoodsAuditEnum :int
     {
         /*
-         * 审核流程 1 领用待确认 2 领用已确认 3 领用确认已拒绝 4 出库待确认 5 出库确认中 6 出库确认完成 7 出库确认拒绝
+         * 审核流程 1 已确认领用 2 已拒绝领用 3 出库待确认 4 出库确认中 5 已完成出库 6 出库确认拒绝
          * 
          */
 
@@ -40,17 +40,17 @@ namespace OASystem.Domain.Enums
         /// <summary>
         /// 出库确认中
         /// </summary>
-        [Description("出库确认中")]
+        [Description("确认中")]
         OutConfirming,
         /// <summary>
         /// 出库确认完成
         /// </summary>
-        [Description("已完成出库")]
+        [Description("已完成")]
         OutConfirmed,
         /// <summary>
         /// 出库确认拒绝
         /// </summary>
-        [Description("已拒绝出库")]
+        [Description("已拒绝")]
         OutRejected,
     }
 
@@ -86,6 +86,11 @@ namespace OASystem.Domain.Enums
     /// </summary>
     public enum GoodsAuditDepEnum : int
     {
+        /// <summary>
+        /// 人事部-前台领用确认
+        /// </summary>
+        [Description("人事部-前台")]
+        Hr_Reception = 0,
         /// <summary>
         /// 人事部
         /// </summary>

+ 4 - 10
OASystem/OASystem.Domain/ViewModels/Financial/Fin_DailyFeePaymentView.cs

@@ -96,16 +96,9 @@ namespace OASystem.Domain.ViewModels.Financial
             {
                 string str = "未审核";
                 if (FAudit == 0) str = "未审核";
-                else if (FAudit == 1)
-                {
-                    str = "已通过";
-                    FAuditName = "朱成梅";
-                }
-                else if (FAudit == 2)
-                {
-                    str = "未通过";
-                    FAuditName = "朱成梅";
-                }
+                else if (FAudit == 1) { str = "已通过"; FAuditName = "朱成梅"; }
+                else if (FAudit == 2) { str = "未通过"; FAuditName = "朱成梅"; }
+                else if (FAudit == 3) { str = "自动审核"; FAuditName = "管理员"; }
                 return str;
             }
         }
@@ -131,6 +124,7 @@ namespace OASystem.Domain.ViewModels.Financial
                 if (MAudit == 0) str = "未审核";
                 else if (MAudit == 1) { str = "已通过"; MAuditName = "张海麟"; }
                 else if (MAudit == 2) { str = "未通过"; MAuditName = "张海麟"; }
+                else if (MAudit == 3) { str = "自动审核"; MAuditName = "管理员"; }
                 return str;
             }
         }

+ 21 - 0
OASystem/OASystem.Domain/ViewModels/Groups/EnterExitCostQuoteView.cs

@@ -18,6 +18,7 @@ namespace OASystem.Domain.ViewModels.Groups
     {
         public int Id { get; set; }
         public string Name { get; set; }
+        public bool IsOnlyRemark { get; set; } = false;
         public int Index { get; set; }
     }
 
@@ -75,6 +76,26 @@ namespace OASystem.Domain.ViewModels.Groups
         public int QuoteId { get; set; }
         public int ItemId { get; set; }
         public string ItemName { get; set; }
+        public bool IsOnlyRemark { get; set; }
+
+        public string ItemWrapName
+        {
+            get {
+                var thisItemName = ItemName;
+                var label = new StringBuilder();
+                if (!string.IsNullOrEmpty(thisItemName))
+                {
+                    if (thisItemName.Contains("\\n"))
+                    {
+                        var strs = thisItemName.Split("\\n");
+                        label.AppendLine(strs[0]);
+                        label.AppendLine(strs[1]);
+                    }
+                    else label.Append(thisItemName);
+                }
+                return label.ToString();
+            }
+        }
 
         public decimal TotalAmt { get { return Infos.Any() ? TruncDecimals(Infos.Sum(x => x.TotalAmt)) : 0.00M; } }
 

+ 1 - 7
OASystem/OASystem.Domain/ViewModels/PersonnelModule/GoodsInfoView.cs

@@ -61,13 +61,7 @@ namespace OASystem.Domain.ViewModels.PersonnelModule
         {
             get
             {
-                var str = "";
-                if (WaitAuditQuantity > 0)
-                {
-                    str = $"物品待审核数量合计:{WaitAuditQuantity.ToString("#0.00")}";
-                }
-
-                return str;
+                return $"物品待审核数量:{WaitAuditQuantity.ToString("#0.00")}";
             }
         }
 

+ 65 - 75
OASystem/OASystem.Infrastructure/Repositories/Financial/DailyFeePaymentRepository.cs

@@ -117,11 +117,22 @@ namespace OASystem.Infrastructure.Repositories.Financial
                                       
             }                         
             var userData1 = userData.Select(x => new { x.Id, x.CnName }).ToList();
+
             //62 公转 63 私转        
             var feeMarkTypeData = setTypeData.Where(s => s.Id == 62 || s.Id == 63).ToList();
             var feeMarkSubTypeData = setData.Where(s => s.STid == 62 || s.STid == 63).ToList();
             var companyNameData = await _CompanyRep.GetCompanyNameData();
 
+            //审核状态
+            var auditStatusData = new List<dynamic>()
+            {
+                new { Id = -1, Name = "全部" },
+                new { Id = 0, Name = "未审核" },
+                new { Id = 1, Name = "已审核" },
+                new { Id = 2, Name = "审核未通过" },
+                new { Id = 3, Name = "自动审核" }
+            };
+
             if (dto.PortType == 1) //web
             {
                 DailyFeePaymentList = new 
@@ -131,7 +142,8 @@ namespace OASystem.Infrastructure.Repositories.Financial
                     UserNameData = userData1,
                     FeeMarkTypeData = feeMarkTypeData,
                     FeeMarkSubTypeData = feeMarkSubTypeData,
-                    CompanyNameData = companyNameData.Data
+                    CompanyNameData = companyNameData.Data,
+                    AuditStatusData = auditStatusData
                 };
             }
             else if (dto.PortType == 2) //安卓
@@ -149,9 +161,43 @@ namespace OASystem.Infrastructure.Repositories.Financial
             result.Msg = "查询成功!";
             result.Data = DailyFeePaymentList;
             return result;
+        }
+
+        /// <summary>
+        /// 总经理自动审核通过类型 
+        /// 90 Parent 各部门基础固定费用明细  
+        /// 104 Parent 团组费用
+        /// 672 Sub 办公费用-信息部申请费用
+        /// </summary>
+        /// <param name="typeId"></param>
+        /// <returns></returns>
+        public async Task<bool> GMAutoApprovalType(int typeId)
+        {
+            if (typeId < 1) return false;
+
+            var parentIds = new List<int>() 
+                {   
+                    90,  // 各部门基础固定费用明细
+                    104, // 团组费用
+                };
+            var subIds = new List<int>()
+                {
+                    672, //办公费用-信息部申请费用
+                };
+
+            var parentTypeDatas = await _sqlSugar.Queryable<Sys_SetData>().Where(x => x.IsDel == 0 && parentIds.Contains(x.STid)).ToListAsync();
+            var subTypeDatas = await _sqlSugar.Queryable<Sys_SetData>().Where(x => x.IsDel == 0 && subIds.Contains(x.Id)).ToListAsync();
 
+            var typeDatas = new List<Sys_SetData>();
+            if (parentTypeDatas.Any()) typeDatas.AddRange(parentTypeDatas);
+            if (subTypeDatas.Any()) typeDatas.AddRange(subTypeDatas);
+
+            if (typeDatas.Any(x => x.Id == typeId)) return true;
+
+            return false;
         }
 
+
         /// <summary>
         /// 日付申请查询 使用的数据源
         /// </summary>
@@ -248,17 +294,8 @@ namespace OASystem.Infrastructure.Repositories.Financial
                     var setData = _setDataTypeRep.QueryDto<Sys_SetData, SetDataView>(s => s.STid == dto.FeeTypeId).ToList();
                     if (setData.Count > 0)
                     {
-                        string setDataIds = "";
-                        foreach (var item in setData)
-                        {
-                            setDataIds += item.Id + ",";
-                        }
-
-                        if (setDataIds.Length > 0)
-                        {
-                            setDataIds = setDataIds.Substring(0, setDataIds.Length - 1);
-                            sqlWhere += string.Format(" And dfp.PriceTypeId In ({0})", setDataIds);
-                        }
+                        string setDataIds = string.Join(",", setData.Select(x => x.Id).ToList());
+                        sqlWhere += string.Format(" And dfp.PriceTypeId In ({0})", setDataIds);
                     }
                 }
             }
@@ -269,7 +306,6 @@ namespace OASystem.Infrastructure.Repositories.Financial
             if (dto.CreateUserId != -1)
                 sqlWhere += string.Format(" And dfp.CreateUserId = {0}", dto.CreateUserId);
 
-
             int startIndex = (dto.PageIndex - 1) * dto.PageSize + 1;
             int endIndex = startIndex + dto.PageSize - 1;
 
@@ -382,40 +418,12 @@ namespace OASystem.Infrastructure.Repositories.Financial
             _fee.CreateUserId = dto.UserId;
             _fee.GroupId = dto.GroupId;
 
-            /*
-             * 2024-10-29
-             * 各部门基础固定费用明细”里的费用数据新增后,财务和总经理审核都默认直接通过isAudit=1),并且可编辑,如果ispay=1的话将不可编辑
-             * 2025-02-24
-             * 团组费用 默认总经理审核通过
-             * 2025-03-25
-             * 各部门基础固定费用明细”里的费用数据新增后,默认老张通过 财务手动审核 
-             * 
-             */
+            //自动审核验证
+            var auditPer  = await GMAutoApprovalType(dto.PriceTypeId);
             var priceTypeInfo = await _sqlSugar.Queryable<Sys_SetData>().FirstAsync(x => x.IsDel == 0 && x.Id == dto.PriceTypeId);
-            if (priceTypeInfo != null && (priceTypeInfo.STid == 90 || priceTypeInfo.STid == 104))
+            if (auditPer)
             {
-
-                //费用类型为团组费用时 验证groupId
-                if (priceTypeInfo.STid == 104)
-                {
-                    var groupInfo = await _sqlSugar.Queryable<Grp_DelegationInfo>().FirstAsync(x => x.IsDel == 0 && x.Id == _fee.GroupId);
-                    if (groupInfo == null)
-                    {
-                        _sqlSugar.RollbackTran();
-
-                        result.Msg = $"请选择有效的团组名称!";
-                        return result;
-                    }
-                }
-
-
-                //if (priceTypeInfo.STid == 90)
-                //{
-                //    _fee.FAudit = 1;
-                //    _fee.FAuditDate = DateTime.Now;
-                //}
-
-                _fee.MAudit = 1;
+                _fee.MAudit = 3;
                 _fee.MAuditDate = DateTime.Now;
             }
 
@@ -451,28 +459,25 @@ namespace OASystem.Infrastructure.Repositories.Financial
         {
             Result result = new Result() { Code = -2 };
 
+            //自动审核验证
+            var auditPer = await GMAutoApprovalType(dto.PriceTypeId);
+
             #region 已审核的数据不可编辑
             var dailyFeeInfo = await _sqlSugar.Queryable<Fin_DailyFeePayment>().Where(it => it.Id == dto.Id && it.IsDel == 0).FirstAsync();
             if (dailyFeeInfo != null)
             {
-                if (dailyFeeInfo.FAudit == 1 || dailyFeeInfo.MAudit == 1)
+                var auditIds = new List<int>() { 1, 3 };
+
+                if (auditIds.Contains(dailyFeeInfo.FAudit) || auditIds.Contains(dailyFeeInfo.MAudit))
                 {
-                    var setData = await _sqlSugar.Queryable<Sys_SetData>().FirstAsync(x => x.IsDel == 0 && x.Id == dto.PriceTypeId);
-                    if (setData != null)
+                    if (auditPer)
                     {
-                        if (setData.STid == 90 || setData.STid == 104)
+                        if (dailyFeeInfo.IsPay == 1)
                         {
-                            if (dailyFeeInfo.IsPay == 1)
-                            {
-                                result.Msg = "该笔费用已付款,不可修改!";
-                                return result;
-                            }
-                        }
-                        else
-                        {
-                            result.Msg = "审核已通过,不可修改!";
+                            result.Msg = "该笔费用已付款,不可修改!";
                             return result;
                         }
+
                     }
                     else
                     {
@@ -489,21 +494,6 @@ namespace OASystem.Infrastructure.Repositories.Financial
             {
                 Fin_DailyFeePayment _fee = _mapper.Map<Fin_DailyFeePayment>(dto);
 
-                /*
-                 * 
-                 * 2025-02-24
-                 * 更改后的费用类型为 团组费用 默认总经理审核通过
-                 * 2025-03-25
-                 * 更改后的费用类型为 各部门基础固定费用明细”里的费用数据新增后,默认老张通过 财务手动审核
-                 * 
-                 */
-                var priceTypeInfo = await _sqlSugar.Queryable<Sys_SetData>().FirstAsync(x => x.IsDel == 0 && x.Id == dto.PriceTypeId);
-                var auditStatus = false;
-                if (priceTypeInfo != null && (priceTypeInfo.STid == 90 || priceTypeInfo.STid == 104))
-                {
-                    auditStatus = true;
-                }
-
                 _fee.CreateUserId = dto.UserId;
                 int? editFeeStatus = await _sqlSugar.Updateable<Fin_DailyFeePayment>()
                     .SetColumns(a => new Fin_DailyFeePayment
@@ -515,8 +505,8 @@ namespace OASystem.Infrastructure.Repositories.Financial
                         CompanyId = dto.CompanyId,
                         GroupId = dto.GroupId,
                     })
-                    .SetColumnsIF(auditStatus, a => a.MAudit == 1)
-                    .SetColumnsIF(auditStatus, a => a.MAuditDate == DateTime.Now)
+                    .SetColumnsIF(auditPer, a => a.MAudit == 3)
+                    .SetColumnsIF(auditPer, a => a.MAuditDate == DateTime.Now)
                     .Where(a => a.Id == dto.Id)
                     .ExecuteCommandAsync();
 

+ 1 - 5
OASystem/OASystem.Infrastructure/Repositories/Groups/DecreasePaymentsRepository.cs

@@ -252,7 +252,7 @@ namespace OASystem.Infrastructure.Repositories.Groups
                         return new JsonView() { Code = 400, Msg = $"添加失败!团组汇率未设置{_sqlSugar.Queryable<Sys_SetData>().First(it => it.IsDel == 0 && it.Id == grp_Decrease.Currency)?.Name ?? ""}该币种汇率!" };
                     }
                     int cId = await _sqlSugar.Insertable(C).ExecuteReturnIdentityAsync();
-                    if (cId != 0)
+                    if (cId > 1)
                     {
                         CommitTran();
                         var data = new { ccpId = cId, sign = 1,dataId = id };
@@ -263,7 +263,6 @@ namespace OASystem.Infrastructure.Repositories.Groups
                         RollbackTran();
                         return new JsonView() { Code = 400, Msg = "添加失败!" };
                     }
-
                 }
             }
             else if (dto.Status == 2)
@@ -346,9 +345,6 @@ namespace OASystem.Infrastructure.Repositories.Groups
                         }
                     }
                 }
-
-                RollbackTran();
-                return new JsonView() { Code = 400, Msg = "修改失败!" };
             }
             RollbackTran();
             return new JsonView() { Code = 400, Msg = MsgTips.Fail }; ;

+ 201 - 19
OASystem/OASystem.Infrastructure/Repositories/Groups/EnterExitCostQuoteRepository.cs

@@ -43,13 +43,23 @@ namespace OASystem.Infrastructure.Repositories.Groups
                 }).ToListAsync();
 
             var newList = origList.Select(x => new InitBasicItemView
-            {
-                Id = x.Id,
-                Name = removeNl ? x.Name.Replace("\\r\\n", "") : x.Name,
-                Index = int.TryParse(x.Index, out int index) ? index : -1
-            })
+                {
+                    Id = x.Id,
+                    Name = removeNl ? x.Name.Replace("\\r\\n", "") : x.Name,
+                    Index = int.TryParse(x.Index, out int index) ? index : -1
+                })
                 .OrderBy(x => x.Index)
                 .ToList();
+
+            var onlyItems = new List<int>() {
+                1358, //邀请函发放对象
+                1360, //邀请函发放时间
+            };
+
+            newList.ForEach(x =>
+            {
+                if (onlyItems.Contains(x.Id)) x.IsOnlyRemark = true;
+            });
             return newList;
         }
 
@@ -166,20 +176,151 @@ namespace OASystem.Infrastructure.Repositories.Groups
         /// <returns></returns>
         public async Task<EnterExitCostQuoteInfoView> InfoAsync(EnterExitCostQuoteInfoDto dto)
         {
+            int quoteId = dto.Id;
             var viewInfo = new EnterExitCostQuoteInfoView();
-            viewInfo.Id = dto.Id;
+            viewInfo.Id = quoteId;
             var basicItems = await InitBasicItemAsync(true);
 
             if (basicItems.Any())
             {
-                viewInfo.FeeItems = basicItems.Select(x => new QuoteItemInfo { ItemId = x.Id, ItemName = x.Name, Index = x.Index }).OrderBy(x => x.Index).ToArray();
+                var quoteItemInfos = new List<QuoteItemInfo>();
+                basicItems.ForEach(x =>
+                {
+                    var quoteSubItemInfos = new List<QuoteSubItemInfo>();
+                    if (x.IsOnlyRemark)
+                    {
+                        quoteSubItemInfos.Add(new QuoteSubItemInfo
+                        {
+                            Id = 0,
+                            ItemId = x.Id,
+                            Index = 1,
+                            FeeName = "",
+                            UnitPrice = 0.00M,
+                            Currency = "CNY",
+                            Quantity = 1.00M,
+                            PplNum = 1,
+                            TotalAmt = 0.00M,
+                            Remark = $"-"
+                        });
+                    }
+
+                    quoteItemInfos.Add(new QuoteItemInfo
+                    {
+                        QuoteId = quoteId,
+                        ItemId = x.Id,
+                        ItemName = x.Name,
+                        IsOnlyRemark = x.IsOnlyRemark,
+                        Infos = quoteSubItemInfos.ToArray(),
+                        Index = x.Index
+                    });
+                });
+
+                viewInfo.FeeItems = quoteItemInfos.OrderBy(x => x.Index).ToArray();
             }
 
             var quoteInfo = await _sqlSugar.Queryable<Grp_EnterExitCostQuote>()
-                 .Where(x => x.IsDel == 0 && x.Id == x.Id)
+                 .Where(x => x.IsDel == 0 && x.Id == quoteId)
                  .FirstAsync();
             if (quoteInfo != null)
             {
+                viewInfo.Id = quoteInfo.Id;
+                viewInfo.Name = quoteInfo.Name;
+                viewInfo.GroupId = quoteInfo.GroupId;
+                viewInfo.Rates = CommonFun.GetCurrencyChinaToList(quoteInfo.CurrencyRemark).ToArray();
+
+                var quoteItems = await _sqlSugar.Queryable<Grp_EnterExitCostQuoteItem>()
+                    .Where(x => x.IsDel == 0 && x.QuoteId == quoteInfo.Id)
+                    .Select(x => new QuoteSubItemInfo
+                    {
+                        Id = x.Id,
+                        ItemId = x.ItemId,
+                        FeeName = x.FeeName,
+                        UnitPrice = x.UnitPrice,
+                        Quantity = x.Quantity,
+                        PplNum = x.PplNum,
+                        Currency = x.Currency,
+                        TotalAmt = x.TotalAmt,
+                        Index = x.Index,
+                        Remark = x.Remark
+                    }).ToListAsync();
+
+                if (quoteItems.Any())
+                {
+                    foreach (var x in viewInfo.FeeItems)
+                    {
+                        var currQuoteInfos = quoteItems.Where(y => y.ItemId == x.ItemId).OrderBy(y => y.Index).ToArray();
+                        if (x.IsOnlyRemark)
+                        {
+                            if (currQuoteInfos.Length > 0)
+                            {
+                                x.Infos = currQuoteInfos;
+                            }
+                        }
+                        else x.Infos = currQuoteInfos;
+                    }
+                }
+            }
+
+            return viewInfo;
+        }
+
+        /// <summary>
+        /// 获取报价详情 By GroupId
+        /// </summary>
+        /// <param name="name"></param>
+        /// <param name="pageIndex"></param>
+        /// <param name="pageSize"></param>
+        /// <returns></returns>
+        public async Task<EnterExitCostQuoteInfoView> InfoByGroupIdAsync(int groupId)
+        {
+            var viewInfo = new EnterExitCostQuoteInfoView();
+
+            var basicItems = await InitBasicItemAsync(true);
+
+            if (basicItems.Any())
+            {
+                var quoteItemInfos = new List<QuoteItemInfo>();
+                basicItems.ForEach(x =>
+                {
+
+                    var quoteSubItemInfos = new List<QuoteSubItemInfo>();
+                    if (x.IsOnlyRemark)
+                    {
+                        quoteSubItemInfos.Add(new QuoteSubItemInfo
+                        {
+                            Id = 0,
+                            ItemId = x.Id,
+                            Index = 1,
+                            FeeName = "",
+                            UnitPrice = 0.00M,
+                            Currency = "CNY",
+                            Quantity = 1.00M,
+                            PplNum = 1,
+                            TotalAmt = 0.00M,
+                            Remark = $"-"
+                        });
+                    }
+
+                    quoteItemInfos.Add(new QuoteItemInfo
+                    {
+                        QuoteId = 0,
+                        ItemId = x.Id,
+                        ItemName = x.Name,
+                        IsOnlyRemark = x.IsOnlyRemark,
+                        Infos = quoteSubItemInfos.ToArray(),
+                        Index = x.Index
+                    });
+                });
+
+                viewInfo.FeeItems = quoteItemInfos.OrderBy(x => x.Index).ToArray();
+            }
+
+            var quoteInfo = await _sqlSugar.Queryable<Grp_EnterExitCostQuote>()
+                 .Where(x => x.IsDel == 0 && x.GroupId == groupId)
+                 .FirstAsync();
+            if (quoteInfo != null)
+            {
+                viewInfo.Id = quoteInfo.Id;
                 viewInfo.Name = quoteInfo.Name;
                 viewInfo.GroupId = quoteInfo.GroupId;
                 viewInfo.Rates = CommonFun.GetCurrencyChinaToList(quoteInfo.CurrencyRemark).ToArray();
@@ -201,7 +342,13 @@ namespace OASystem.Infrastructure.Repositories.Groups
 
                 if (quoteItems.Any())
                 {
-                    viewInfo.FeeItems = viewInfo.FeeItems.Select(x => new QuoteItemInfo { Index = x.Index, QuoteId = dto.Id, ItemId = x.ItemId, ItemName = x.ItemName, Infos = quoteItems.Where(y => y.ItemId == x.ItemId).OrderBy(y => y.Index).ToArray() }).ToArray();
+                    //viewInfo.FeeItems = viewInfo.FeeItems.Select(x => new QuoteItemInfo { Index = x.Index, QuoteId = quoteInfo.Id, ItemId = x.ItemId, ItemName = x.ItemName, Infos = quoteItems.Where(y => y.ItemId == x.ItemId).OrderBy(y => y.Index).ToArray() }).ToArray();
+
+                    viewInfo.FeeItems.ForEach(x =>
+                    {
+                        x.QuoteId = quoteInfo.Id;
+                        x.Infos = quoteItems.Where(y => y.ItemId == x.ItemId).OrderBy(y => y.Index).ToArray(); ;
+                    });
                 }
             }
 
@@ -260,7 +407,7 @@ namespace OASystem.Infrastructure.Repositories.Groups
                 }
             }
 
-            var isNull = await _sqlSugar.Queryable<Grp_EnterExitCostQuote>().FirstAsync(x => x.IsDel == 0 && x.Name.Equals(quoteName)) == null ? true : false;
+            var isNull = await _sqlSugar.Queryable<Grp_EnterExitCostQuote>().FirstAsync(x => x.IsDel == 0 && x.Id == quoteId) == null ? true : false;
 
             _sqlSugar.BeginTran();
 
@@ -286,7 +433,9 @@ namespace OASystem.Infrastructure.Repositories.Groups
             }
             else if (!isNull) //编辑
             {
-                var quoteUpd = await _sqlSugar.Updateable(quoteInfo).IgnoreColumns(x => new { x.CreateUserId, x.CreateTime, x.IsDel }).ExecuteCommandAsync();
+                var quoteUpd = await _sqlSugar.Updateable(quoteInfo)
+                    .IgnoreColumns(x => new { x.CreateUserId, x.CreateTime, x.IsDel })
+                    .ExecuteCommandAsync();
                 if (quoteUpd < 1)
                 {
                     jw.Msg = "编辑失败!";
@@ -294,16 +443,19 @@ namespace OASystem.Infrastructure.Repositories.Groups
                     return jw;
                 }
 
-                var addItems = quoteItemInfos.Where(x => x.Id < 1).ToList();
+                var insertItems = quoteItemInfos.Where(x => x.Id < 1).ToList();
                 var updItems = quoteItemInfos.Where(x => x.Id > 0).ToList();
-                if (addItems.Any())
+                if (insertItems.Any())
                 {
-                    var addItem = await _sqlSugar.Insertable(addItems).ExecuteCommandAsync();
-                    if (addItem < 1)
-                    {
-                        jw.Msg = "编辑失败!";
-                        _sqlSugar.RollbackTran();
-                        return jw;
+                    foreach (var item in insertItems) {
+                        var insertInfo = await _sqlSugar.Insertable(item).ExecuteReturnEntityAsync();
+                        if (insertInfo == null)
+                        {
+                            jw.Msg = "编辑失败!";
+                            _sqlSugar.RollbackTran();
+                            return jw;
+                        }
+                        quoteItemInfos.Add(insertInfo);
                     }
                 }
 
@@ -317,6 +469,36 @@ namespace OASystem.Infrastructure.Repositories.Groups
                         return jw;
                     }
                 }
+
+                //验证及处理前台删除项数据
+                var perDelItems = await _sqlSugar.Queryable<Grp_EnterExitCostQuoteItem>()
+                    .Where(x => x.IsDel == 0 && x.QuoteId == quoteId)
+                    .ToListAsync();
+                if (perDelItems.Any())
+                {
+                    var delItems = perDelItems.Where(x => !quoteItemInfos.Select(y => y.Id).Contains(x.Id)).ToList();
+                    if (delItems.Any())
+                    {
+                        var newDelItems = delItems.Select(x =>
+                            new Grp_EnterExitCostQuoteItem
+                            {
+                                Id = x.Id,
+                                DeleteTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
+                                DeleteUserId = dto.CurrUserId,
+                                IsDel = 1
+                            }).ToList();
+                        var delItemStatus = await _sqlSugar.Updateable(newDelItems)
+                            .UpdateColumns(x => new { x.DeleteTime, x.DeleteUserId, x.IsDel })
+                            .ExecuteCommandAsync();
+                        if (delItemStatus < 1)
+                        {
+                            jw.Msg = "移除项费用失败!";
+                            _sqlSugar.RollbackTran();
+                            return jw;
+                        }
+                    }
+                }
+
                 jw.Msg = "编辑成功!";
             }
 

+ 636 - 89
OASystem/OASystem.Infrastructure/Repositories/PersonnelModule/GoodsRepository.cs

@@ -1,5 +1,6 @@
 using Aspose.Cells;
 using AutoMapper;
+using EyeSoft.Runtime.InteropServices;
 using Newtonsoft.Json;
 using OASystem.Domain;
 using OASystem.Domain.Dtos.PersonnelModule;
@@ -872,7 +873,6 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
 
             if (auditType == 1)//入库
             {
-
                 hrAuditorIds.AuditorIds = new int[] {
                     //343,    // 陈湘 
                     374,    // 罗颖
@@ -1400,6 +1400,27 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
                             !auditEnums.Contains(x.AuditStatus)
                 ).SumAsync(x => x.Quantity);
 
+            //验证默认审核 多条 or 单条
+            //出库确认默认审核状态
+            var isAuditPer = GoodsAuditType(goodsInfo?.Type ?? 0);
+
+            //验证默认审核 多条审核时添加
+            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.Append($"领用确认:状态:待确认  审核人:-  审核时间:-;<br/>");
+
+            if (isAuditPer)
+            {
+                    goodsAuditInfos.Add(goodsAuditInfo2);
+                    stringBuilder.Append($"人事部:状态:待确认  审核人:-  审核时间:-;<br/>");
+            }
+
+            info.StatusDesc = stringBuilder.ToString();
+
             if (info.Id > 0) //修改
             {
                 //审核验证
@@ -1427,29 +1448,20 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
                         x.Quantity,
                         x.Reason,
                         x.Remark,
+                        x.StatusDesc,
                     })
                     .Where(x => x.Id == info.Id)
                     .ExecuteCommandAsync();
                 if (edit > 0)
                 {
+                    var auditInfos = await _sqlSugar.Queryable<Pm_GoodsAudit>().Where(x => x.DataId == info.Id).ToListAsync();
+                    if (!auditInfos.Any()) await _sqlSugar.Insertable(goodsAuditInfos).ExecuteCommandAsync();
+
                     _sqlSugar.CommitTran();
                     _jv.Msg = $"操作成功!";
                     _jv.Code = StatusCodes.Status200OK;
                     return _jv;
                 }
-
-                //验证默认审核 多条 or 单挑
-                var isAuditPer = GoodsAuditType(goodsInfo?.Type ?? 0);
-                if (!isAuditPer)
-                {
-                    //出库确认默认审核状态
-                    var goodsAuditList = new List<Pm_GoodsAudit>() {
-                        new (2, GoodsAuditDepEnum.Hr, info.Id, GoodsConfirmEnum.WaitConfirm, currUserId),
-                        //new (2, GoodsAuditDepEnum.Financial, add, GoodsConfirmEnum.WaitConfirm, currUserId)
-                        };
-                    await _sqlSugar.Insertable(goodsAuditList).ExecuteCommandAsync();
-                }
-
             }
             else if (info.Id < 1) //添加
             {
@@ -1463,30 +1475,16 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
                 }
 
                 var add = await _sqlSugar.Insertable(info).ExecuteReturnIdentityAsync();
-                if (add < 1)
+                if (add > 0)
                 {
-                    _sqlSugar.RollbackTran();
-                    _jv.Msg = $"添加失败!";
-                    _jv.Code = StatusCodes.Status400BadRequest;
-                    return _jv;
-                }
+                    goodsAuditInfos.ForEach(x => x.DataId = add);
+                    await _sqlSugar.Insertable(goodsAuditInfos).ExecuteCommandAsync();
 
-                //验证默认审核 多条 or 单挑
-                var isAuditPer = GoodsAuditType(goodsInfo?.Type ?? 0);
-                if (isAuditPer)
-                {
-                    //出库确认默认审核状态
-                    var goodsAuditList = new List<Pm_GoodsAudit>() {
-                        new (2, GoodsAuditDepEnum.Hr, add, GoodsConfirmEnum.WaitConfirm, currUserId),
-                        //new (2, GoodsAuditDepEnum.Financial, add, GoodsConfirmEnum.WaitConfirm, currUserId)
-                        };
-                    await _sqlSugar.Insertable(goodsAuditList).ExecuteCommandAsync();
+                    _sqlSugar.CommitTran();
+                    _jv.Msg = $"操作成功!";
+                    _jv.Code = StatusCodes.Status200OK;
+                    return _jv;
                 }
-
-                _sqlSugar.CommitTran();
-                _jv.Msg = $"操作成功!";
-                _jv.Code = StatusCodes.Status200OK;
-                return _jv;
             }
             _sqlSugar.RollbackTran();
             return _jv;
@@ -1503,47 +1501,18 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
         {
             if (idArray.Length < 1) return _jv;
 
-            var auditEnums = new List<GoodsAuditEnum>() {
-                GoodsAuditEnum.Pending,
-                GoodsAuditEnum.Approved,
-                GoodsAuditEnum.UnApproved,
-                GoodsAuditEnum.OutPending,
-                GoodsAuditEnum.OutConfirmed,
-                GoodsAuditEnum.OutRejected,
-            };
-
-            if (!auditEnums.Contains(auditEnum))
+            if (!Enum.IsDefined(typeof(GoodsAuditEnum),(int)auditEnum))
             {
                 _jv.Msg = $"出库确认状态超出可用范围!";
                 return _jv;
             }
 
-
             int receiveId = idArray[0];
 
-            //验证审核部门 审核状态 大于等于 OutPending 时 验证
-            var auditDep = GoodsAuditDepEnum.Hr;
-            if (auditEnum >= GoodsAuditEnum.OutPending)
-            {
-                var auditList = GoodsStorageConfirmAuditDep(2);
-                var auditDepInfo = auditList.Find(x => x.AuditorIds.Contains(userId));
-                if (auditDepInfo == null)
-                {
-                    _jv.Msg = string.Format("未分配出库确认权限!");
-                    return _jv;
-                }
-
-                auditDep = auditDepInfo.AuditDep;
-            }
-
             var currUserName = _sqlSugar.Queryable<Sys_Users>().First(x => x.Id == userId)?.CnName ?? "-";
 
             _sqlSugar.BeginTran();
-            var receiveInfo = await _sqlSugar
-                .Queryable<Pm_GoodsReceive>()
-                //.Where(x => x.IsDel == 0 && idArray.Contains(x.Id))
-                .Where(x => x.IsDel == 0 && receiveId == x.Id)
-                .FirstAsync();
+            var receiveInfo = await _sqlSugar.Queryable<Pm_GoodsReceive>().FirstAsync(x => x.IsDel == 0 && receiveId == x.Id);
 
             if (receiveInfo == null)
             {
@@ -1552,6 +1521,10 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
                 return _jv;
             }
 
+            var goodsInfo = await _sqlSugar.Queryable<Pm_GoodsInfo>().FirstAsync(x => x.Id == receiveInfo.GoodsId);
+
+            int goodTypeId = goodsInfo?.Type ?? 0;
+
             //审核前状态
             var preChangeStatus = receiveInfo.AuditStatus;
 
@@ -1563,27 +1536,60 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
             //    return _jv;
             //}
 
-            switch (auditEnum)
-            {
-                case GoodsAuditEnum.Pending: //领用待确认(取消确认、取消拒绝)
-                    _jv = await GoodsReceivePending(preChangeStatus, receiveId, userId, currUserName, auditEnum);
-                    break;
-                case GoodsAuditEnum.Approved: //领用确认
-                    _jv = await GoodsReceiveApproved(preChangeStatus, receiveId, userId, currUserName, auditEnum);
-                    break;
-                case GoodsAuditEnum.UnApproved: //领用拒绝
-                    _jv = await GoodsReceiveUnApproved(preChangeStatus, receiveId, userId, currUserName, auditEnum);
-                    break;
-                case GoodsAuditEnum.OutPending: //出库待确认(取消出库确认、取消出库拒绝)
-                    _jv = await GoodsReceiveOutPending(preChangeStatus, receiveInfo, userId, auditDep, auditEnum);
-                    break;
-                case GoodsAuditEnum.OutConfirmed: //出库确认
-                    _jv = await GoodsReceiveOutConfirming(receiveInfo, userId, auditDep, auditEnum);
-
-                    break;
-                case GoodsAuditEnum.OutRejected:  //出库拒绝
-                    _jv = await GoodsReceiveOutConfirming(receiveInfo, userId, auditDep, auditEnum);
-                    break;
+            var isAuditPer = GoodsAuditType(goodTypeId);
+
+            if (isAuditPer) //多人审核
+            {
+                var auditDep = GoodsAuditDepEnum.Hr_Reception;
+
+                var auditInfo = await _sqlSugar.Queryable<Pm_GoodsAudit>()
+                    .FirstAsync(x => x.Type == 2 && x.DataId == receiveInfo.Id && x.Dep == GoodsAuditDepEnum.Hr_Reception);
+                if (auditInfo != null && auditInfo.AuditStatus == GoodsConfirmEnum.Confirmed)
+                {
+                    auditDep = GoodsAuditDepEnum.Hr;
+
+                    //多人审核的时候验证审核权限
+                    var auditList = GoodsStorageConfirmAuditDep(2);
+                    var auditDepInfo = auditList.Find(x => x.AuditorIds.Contains(userId));
+                    if (auditDepInfo == null)
+                    {
+                        _jv.Msg = string.Format("未分配出库确认权限!");
+                        _sqlSugar.RollbackTran();
+                        return _jv;
+                    }
+                }
+
+                // 确认中 确认 拒绝 
+                _jv = await GoodsReceiveOutConfirmingMultiple(receiveInfo, userId, auditDep, auditEnum);
+
+                //switch (auditEnum)
+                //{
+                //    case GoodsAuditEnum.Pending: //领用待确认(取消确认、取消拒绝)
+                //        _jv = await GoodsReceivePending(preChangeStatus, receiveId, userId, currUserName, auditEnum);
+                //        break;
+                //    case GoodsAuditEnum.Approved: //领用确认
+                //        _jv = await GoodsReceiveApproved(preChangeStatus, receiveId, userId, currUserName, auditEnum);
+                //        break;
+                //    case GoodsAuditEnum.UnApproved: //领用拒绝
+                //        _jv = await GoodsReceiveUnApproved(preChangeStatus, receiveId, userId, currUserName, auditEnum);
+                //        break;
+                //    case GoodsAuditEnum.OutPending: //出库待确认(取消出库确认、取消出库拒绝)
+                //        _jv = await GoodsReceiveOutPending(preChangeStatus, receiveInfo, userId, auditDep, auditEnum);
+                //        break;
+                //    case GoodsAuditEnum.OutConfirmed: //出库确认
+                //        _jv = await GoodsReceiveOutConfirming(receiveInfo, userId, auditDep, auditEnum);
+                //        break;
+                //    case GoodsAuditEnum.OutRejected:  //出库拒绝
+                //        _jv = await GoodsReceiveOutConfirming(receiveInfo, userId, auditDep, auditEnum);
+                //        break;
+                //}
+
+            }
+            else //单人审核 
+            {
+                //领用确认 --> 已确认 / 领用拒绝 --> 已拒绝
+                _jv = await GoodsReceiveOutConfirmingSingle(receiveInfo,userId, currUserName,auditEnum);
+                
             }
 
             if (_jv.Code == StatusCodes.Status200OK)
@@ -1598,6 +1604,8 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
             return _jv;
         }
 
+        #region 多人审核状态变更
+
         /// <summary>
         /// 物品领用状态 - 领用待确认(取消确认、取消拒绝)
         /// </summary>
@@ -2024,8 +2032,6 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
                 statusDesc.Append(auditInfStatusDesc);
             }
 
-
-
             if (preChangeStatus == auditEnum)
             {
                 _jv.Msg = $"此操作已执行,不可重复操作!";
@@ -2196,6 +2202,547 @@ namespace OASystem.Infrastructure.Repositories.PersonnelModule
             return _jv;
         }
 
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="receiveInfo"></param>
+        /// <param name="userId"></param>
+        /// <param name="depEnum"></param>
+        /// <param name="auditEnum"></param>
+        /// <returns></returns>
+        public async Task<JsonView> GoodsReceiveOutConfirmingMultiple(Pm_GoodsReceive receiveInfo, int userId, GoodsAuditDepEnum depEnum, GoodsAuditEnum auditEnum)
+        {
+            _jv.Code = StatusCodes.Status400BadRequest;
+
+            //更改前状态
+            receiveInfo.CreateUserId = userId;
+            var preChangeStatus = receiveInfo.AuditStatus;
+            var currUserOpDt = DateTime.Now;
+            var currUserOpTime = currUserOpDt.ToString("yyyy-MM-dd HH:mm:ss");
+            var receiveUserName = _sqlSugar.Queryable<Sys_Users>().First(x => x.Id == receiveInfo.AuditUserId)?.CnName ?? "-";
+
+            var auditInfos = await _sqlSugar.Queryable<Pm_GoodsAudit>()
+                .Where(x => x.IsDel == 0 && x.DataId == receiveInfo.Id && x.Type == 2)
+                .ToListAsync();
+
+            var auditStatus = GoodsConfirmEnum.WaitConfirm;
+            if (auditEnum == GoodsAuditEnum.UnApproved) auditStatus = GoodsConfirmEnum.UnApproved;
+            else if (auditEnum == GoodsAuditEnum.Approved) auditStatus = GoodsConfirmEnum.Confirmed;
+
+            var auditInfo = auditInfos.Find(x => x.Dep == depEnum);
+
+            if (auditInfo == null)
+            {
+                auditInfo = new Pm_GoodsAudit(2, depEnum, receiveInfo.Id, auditStatus, userId);
+                auditInfo.AuditUserId = userId;
+                var addStatus = await _sqlSugar.Insertable(auditInfo).ExecuteCommandAsync();
+                if (addStatus < 1)
+                {
+                    _jv.Msg = $"出库确认操作失败!";
+                    return _jv;
+                }
+                auditInfos.Add(auditInfo);
+            }
+            else
+            {
+                //移除旧数据
+                auditInfos.Remove(auditInfo);
+                auditInfo.AuditStatus = auditStatus;
+                auditInfo.AuditUserId = userId;
+                auditInfo.AuditTime = currUserOpDt;
+                var updStatus = await _sqlSugar.Updateable<Pm_GoodsAudit>()
+                    .SetColumns(x => new Pm_GoodsAudit()
+                    {
+                        AuditStatus = auditStatus,
+                        AuditUserId = userId,
+                        AuditTime = currUserOpDt
+                    })
+                    .Where(x => x.Id == auditInfo.Id)
+                    .ExecuteCommandAsync();
+
+                if (updStatus < 1)
+                {
+                    _jv.Msg = $"出库确认操作失败!";
+                    return _jv;
+                }
+
+                //添加更新后的数据
+                auditInfos.Add(auditInfo);
+            }
+            auditInfos = auditInfos.OrderBy(x => x.Dep).ToList();
+            //处理状态描述
+            StringBuilder statusDesc = new StringBuilder();
+            foreach (var auditInf in auditInfos)
+            {
+                string auditType = auditInf.Dep == GoodsAuditDepEnum.Hr ? "人事部" : "领用确认";
+                string userName = _sqlSugar.Queryable<Sys_Users>().First(x => x.Id == auditInf.AuditUserId)?.CnName ?? "-";
+                string userOpTime = !userName.Equals("-") ? auditInf.AuditTime.ToString("yyyy-MM-dd HH:mm:ss") : "-";
+                string auditInfStatusDesc = string.Format("{0}:状态:{1}  审核人:{2}  审核时间:{3};<br/>",
+                       auditType, auditInf.AuditStatus.GetEnumDescription(), userName, currUserOpTime);
+                statusDesc.Append(auditInfStatusDesc);
+            }
+
+            if (preChangeStatus == auditEnum)
+            {
+                _jv.Msg = $"此操作已执行,不可重复操作!";
+                return _jv;
+            }
+
+            //批次库存信息
+            string goodsStorageInfo = receiveInfo.GoodsStorageInfo;
+
+            //更改领用状态及库存
+            if (auditInfos.Any(x => x.AuditStatus == GoodsConfirmEnum.UnApproved))
+            {
+                //出库确认拒绝
+                auditEnum = GoodsAuditEnum.OutRejected;
+
+                if (preChangeStatus == GoodsAuditEnum.OutConfirmed)
+                {
+                    //回滚库存
+                    _jv = await GoodsInventoryRollback(receiveInfo);
+                    if (_jv.Code != StatusCodes.Status200OK) return _jv;
+                }
+
+            }
+            else if (auditInfos.Where(x => x.AuditStatus == GoodsConfirmEnum.Confirmed).Count() == 2)
+            {
+                //1.出库确认完成
+                auditEnum = GoodsAuditEnum.OutConfirmed;
+
+                //2.更改前的状态为出库确认中 且 更改后的状态为出库确认完成 执行库存减操作
+                if (preChangeStatus == GoodsAuditEnum.OutConfirming || preChangeStatus == GoodsAuditEnum.OutRejected)
+                {
+                    //2.1 更改库存
+                    var goodsInfo = await _sqlSugar.Queryable<Pm_GoodsInfo>().Where(x => x.Id == receiveInfo.GoodsId).FirstAsync();
+                    goodsInfo.StockQuantity -= receiveInfo.Quantity;
+                    goodsInfo.OQ_Total += receiveInfo.Quantity;
+                    goodsInfo.LastUpdateTime = DateTime.Now;
+                    goodsInfo.LastUpdateUserId = userId;
+
+                    var editGoods = await _sqlSugar
+                        .Updateable(goodsInfo)
+                        .UpdateColumns(x => new
+                        {
+                            x.StockQuantity,
+                            x.OQ_Total,
+                            x.LastUpdateUserId,
+                            x.LastUpdateTime,
+                        })
+                        .Where(x => x.Id == receiveInfo.GoodsId)
+                        .ExecuteCommandAsync();
+
+                    if (editGoods < 1)
+                    {
+                        _jv.Msg = $"库存更新失败!";
+                        return _jv;
+                    }
+
+                    //2.2 入库批次关联领用人 更改批次库存
+                    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);
+                    }
+
+                    //2.2.1 更改批次库存
+                    if (goodsReceiveInfos.Count > 0)
+                    {
+                        var edit1 = await _sqlSugar.Updateable(batchStorageInfos)
+                            .UpdateColumns(x => x.ReceiveQuantity)
+                            .WhereColumns(x => x.Id)
+                            .ExecuteCommandAsync();
+                        if (edit1 < 1)
+                        {
+                            _jv.Msg = $"批次库存更新失败!";
+                            return _jv;
+                        }
+                    }
+
+                    //2.2.2 添加入库批次关联领用人
+                    if (goodsReceiveInfos.Count > 0)
+                    {
+                        goodsStorageInfo = JsonConvert.SerializeObject(goodsReceiveInfos);
+                    }
+                }
+
+            }
+            else if (auditInfos.Where(x => x.AuditStatus == GoodsConfirmEnum.Confirmed).Count() == 1)
+            {
+                //出库确认中
+                auditEnum = GoodsAuditEnum.OutConfirming;
+
+                if (preChangeStatus == GoodsAuditEnum.OutConfirmed)
+                {
+                    //回滚库存
+                    _jv = await GoodsInventoryRollback(receiveInfo);
+                    if (_jv.Code != StatusCodes.Status200OK) return _jv;
+                }
+            }
+            else auditEnum = GoodsAuditEnum.OutPending;
+
+            var statusDesc1 = statusDesc.ToString();
+
+            var changeStatus = await _sqlSugar
+                .Updateable<Pm_GoodsReceive>()
+                .SetColumns(x => new Pm_GoodsReceive()
+                {
+                    AuditStatus = auditEnum,
+                    StatusDesc = statusDesc1,
+                    GoodsStorageInfo = goodsStorageInfo,
+                })
+                .Where(x => x.Id == receiveInfo.Id)
+                .ExecuteCommandAsync();
+
+            if (changeStatus > 0)
+            {
+                _jv.Code = StatusCodes.Status200OK;
+            }
+
+            return _jv;
+        }
+
+        /// <summary>
+        /// 物品库存回滚
+        /// </summary>
+        /// <param name="receiveInfo"></param>
+        /// <returns></returns>
+        public async Task<JsonView> GoodsInventoryRollback(Pm_GoodsReceive receiveInfo)
+        {
+            var goodsInfo = await _sqlSugar.Queryable<Pm_GoodsInfo>().FirstAsync(x => x.Id == receiveInfo.GoodsId);
+
+            //回滚库存
+            var changeGoods = await _sqlSugar
+                .Updateable(goodsInfo)
+                .ReSetValue(it => {
+                    it.StockQuantity += receiveInfo.Quantity;
+                    it.OQ_Total -= receiveInfo.Quantity;
+                    it.LastUpdateTime = DateTime.Now;
+                    it.LastUpdateUserId = receiveInfo.CreateUserId;
+                })
+                .ExecuteCommandAsync();
+
+            if (changeGoods < 1)
+            {
+                _jv.Msg = $"库存回滚失败!";
+                return _jv;
+            }
+            //批次领用记录
+            _jv.Code = StatusCodes.Status200OK;
+            var goodsStorageInfo = receiveInfo.GoodsStorageInfo;
+
+            if (string.IsNullOrEmpty(goodsStorageInfo)) return _jv;
+
+            var goodsStorageInfos = JsonConvert.DeserializeObject<List<GoodsReceiveLinkStorageView>>(goodsStorageInfo);
+
+            if (!goodsStorageInfos.Any()) return _jv;
+
+            foreach (var item in goodsStorageInfos)
+            {
+                var newStorageInfo = await _sqlSugar.Queryable<Pm_GoodsStorage>()
+                    .Where(x => x.IsDel == 0 && x.Id == item.StorageId)
+                    .FirstAsync();
+                if (newStorageInfo == null) continue;
+
+                var newEdit = await _sqlSugar.Updateable(newStorageInfo)
+                        .ReSetValue(x => x.ReceiveQuantity = x.ReceiveQuantity - item.Quantity)
+                        .ExecuteCommandAsync();
+
+                if (newEdit < 1)
+                {
+                    _jv.Code = StatusCodes.Status400BadRequest;
+                    _jv.Msg = $"批次领用库存更新失败!";
+                    return _jv;
+                }
+            }
+
+            _jv.Code = StatusCodes.Status200OK;
+            return _jv;
+        }
+
+        #endregion
+
+        #region 单人审核状态变更
+
+        /// <summary>
+        /// 物品领用状态 - 出库确认完成、出库确认拒绝
+        /// </summary>
+        /// <param name="receiveInfo"></param>
+        /// <param name="userId"></param>
+        /// <param name="currUserName"></param>
+        /// <param name="auditEnum"></param>
+        /// <returns></returns>
+        public async Task<JsonView> GoodsReceiveOutConfirmingSingle(Pm_GoodsReceive receiveInfo, int userId,string currUserName,GoodsAuditEnum auditEnum)
+        {
+            _jv.Code = StatusCodes.Status400BadRequest;
+
+            //状态操作范围验证
+            var auditEnums = new List<GoodsAuditEnum>() {
+                GoodsAuditEnum.Pending,
+                GoodsAuditEnum.Approved,
+                GoodsAuditEnum.UnApproved,
+            };
+
+            if (!auditEnums.Contains(auditEnum))
+            {
+                _jv.Msg = $"{GoodsAuditEnum.Pending.GetEnumDescription()}、{GoodsAuditEnum.OutConfirmed.GetEnumDescription()}、{GoodsAuditEnum.OutRejected.GetEnumDescription()},状态下可操作!";
+                return _jv;
+            }
+
+            var currUserOpDt = DateTime.Now;
+            var currUserOpTime = currUserOpDt.ToString("yyyy-MM-dd HH:mm:ss");
+
+            //更改前状态
+            var preChangeStatus = receiveInfo.AuditStatus;
+
+            //前台状态验证
+            var auditInfo = await _sqlSugar.Queryable<Pm_GoodsAudit>().FirstAsync(x => x.IsDel == 0 && x.Type == 2 && x.DataId == receiveInfo.Id);
+            if (auditInfo == null)
+            {
+                var addInfo = new Pm_GoodsAudit(2, GoodsAuditDepEnum.Hr_Reception, receiveInfo.Id, GoodsConfirmEnum.WaitConfirm, userId);
+                auditInfo = await _sqlSugar.Insertable(addInfo).ExecuteReturnEntityAsync();
+                if (auditInfo == null)
+                {
+                    _jv.Msg = $"确认操作失败!";
+                    return _jv;
+                }
+            }
+
+            if (auditEnum == GoodsAuditEnum.Approved)
+            {
+                auditInfo.AuditStatus = GoodsConfirmEnum.Confirmed;
+                auditEnum = GoodsAuditEnum.OutConfirmed;
+            }
+            else if (auditEnum == GoodsAuditEnum.UnApproved)
+            {
+                auditInfo.AuditStatus = GoodsConfirmEnum.UnApproved;
+                auditEnum = GoodsAuditEnum.OutRejected;
+            }
+
+            if (preChangeStatus == auditEnum)
+            {
+                _jv.Msg = $"此操作已执行,不可重复操作!";
+                return _jv;
+            }
+
+            //更新子表审核状态
+            var updStatus = await _sqlSugar.Updateable<Pm_GoodsAudit>()
+                    .SetColumns(x => new Pm_GoodsAudit()
+                    {
+                        AuditStatus = auditInfo.AuditStatus,
+                        AuditUserId = userId,
+                        AuditTime = currUserOpDt
+                    })
+                    .Where(x => x.Id == auditInfo.Id)
+                    .ExecuteCommandAsync();
+
+            if (updStatus < 1)
+            {
+                _jv.Msg = $"确认操作失败!";
+                return _jv;
+            }
+
+            //处理状态描述
+            StringBuilder statusDesc = new StringBuilder();
+            statusDesc.Append(string.Format("领用确认:状态:{0}  审核人:{1}  审核时间:{2};", auditInfo.AuditStatus.GetEnumDescription(), currUserName, currUserOpTime));
+            
+            //批次库存信息
+            string goodsStorageInfo = receiveInfo.GoodsStorageInfo;
+
+            if (auditEnum == GoodsAuditEnum.OutConfirmed) //出库确认
+            {
+                //1 更改库存
+                var goodsInfo = await _sqlSugar.Queryable<Pm_GoodsInfo>().Where(x => x.Id == receiveInfo.GoodsId).FirstAsync();
+                goodsInfo.StockQuantity -= receiveInfo.Quantity;
+                goodsInfo.OQ_Total += receiveInfo.Quantity;
+                goodsInfo.LastUpdateTime = DateTime.Now;
+                goodsInfo.LastUpdateUserId = userId;
+
+                var editGoods = await _sqlSugar.Updateable(goodsInfo)
+                    .UpdateColumns(x => new
+                    {
+                        x.StockQuantity,
+                        x.OQ_Total,
+                        x.LastUpdateUserId,
+                        x.LastUpdateTime,
+                    })
+                    .Where(x => x.Id == receiveInfo.GoodsId)
+                    .ExecuteCommandAsync();
+
+                if (editGoods < 1)
+                {
+                    _jv.Msg = $"库存更新失败!";
+                    return _jv;
+                }
+
+                //2 入库批次关联领用人 更改批次库存
+                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);
+                }
+
+                //3 更改批次库存
+                if (goodsReceiveInfos.Count > 0)
+                {
+                    var edit1 = await _sqlSugar.Updateable(batchStorageInfos)
+                        .UpdateColumns(x => x.ReceiveQuantity)
+                        .WhereColumns(x => x.Id)
+                        .ExecuteCommandAsync();
+                    if (edit1 < 1)
+                    {
+                        _jv.Msg = $"批次库存更新失败!";
+                        return _jv;
+                    }
+                }
+
+                //4 添加入库批次关联领用人
+                if (goodsReceiveInfos.Count > 0)
+                {
+                    goodsStorageInfo = JsonConvert.SerializeObject(goodsReceiveInfos);
+                }
+
+
+            }
+            else if (auditEnum == GoodsAuditEnum.OutRejected) //出库拒绝
+            {
+                //拒绝之前的状态为已完成 回滚库存
+                if (preChangeStatus == GoodsAuditEnum.OutConfirmed)
+                {
+                    //回滚库存
+                    var goodsInfo = await _sqlSugar.Queryable<Pm_GoodsInfo>().FirstAsync(x => x.Id == receiveInfo.GoodsId);
+
+                    var changeGoods = await _sqlSugar
+                        .Updateable(goodsInfo)
+                        .ReSetValue(it => {
+                            it.StockQuantity += receiveInfo.Quantity;
+                            it.OQ_Total -= receiveInfo.Quantity;
+                            it.LastUpdateTime = DateTime.Now;
+                            it.LastUpdateUserId = userId;
+                        })
+                        .ExecuteCommandAsync();
+
+                    if (changeGoods < 1)
+                    {
+                        _jv.Msg = $"库存回滚失败!";
+                        return _jv;
+                    }
+
+                    //批次号库存 信息更新
+                    var goodsStorageInfo1 = receiveInfo.GoodsStorageInfo;
+                    if (!string.IsNullOrEmpty(goodsStorageInfo))
+                    {
+                        var goodsStorageInfos = JsonConvert.DeserializeObject<List<GoodsReceiveLinkStorageView>>(goodsStorageInfo);
+                        if (goodsStorageInfos.Any())
+                        {
+                            foreach (var item in goodsStorageInfos)
+                            {
+                                var newStorageInfo = await _sqlSugar.Queryable<Pm_GoodsStorage>()
+                                    .Where(x => x.IsDel == 0 && x.Id == item.StorageId)
+                                    .FirstAsync();
+                                if (newStorageInfo == null) continue;
+
+                                var newEdit = await _sqlSugar.Updateable(newStorageInfo)
+                                        .ReSetValue(x => x.ReceiveQuantity = x.ReceiveQuantity - item.Quantity)
+                                        .ExecuteCommandAsync();
+
+                                if (newEdit < 1)
+                                {
+                                    _jv.Msg = $"批次领用库存更新失败!";
+                                    return _jv;
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+
+            var statusDesc1 = statusDesc.ToString();
+
+            var changeStatus = await _sqlSugar
+                .Updateable<Pm_GoodsReceive>()
+                .SetColumns(x => new Pm_GoodsReceive()
+                {
+                    AuditStatus = auditEnum,
+                    StatusDesc = statusDesc1,
+                    GoodsStorageInfo = goodsStorageInfo,
+                })
+                .Where(x => x.Id == receiveInfo.Id)
+                .ExecuteCommandAsync();
+
+            if (changeStatus > 0) _jv.Code = StatusCodes.Status200OK;
+
+            return _jv;
+        }
+
+        #endregion
+
         /// <summary>
         /// 物品领用 Del
         /// </summary>