From 834294889ab62bafaf034b1b87c2ead961c33476 Mon Sep 17 00:00:00 2001
From: wangxinhui <wangxinhui@hnkhzn.com>
Date: 星期五, 05 十二月 2025 09:37:46 +0800
Subject: [PATCH] 更新最新代码

---
 项目代码/WMS/WMSServices/WIDESEA_TaskInfoService/MesTaskService.cs |  321 +++++++++++++++++++++++++++++++++++++++++------------
 1 files changed, 248 insertions(+), 73 deletions(-)

diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS/WMSServices/WIDESEA_TaskInfoService/MesTaskService.cs" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS/WMSServices/WIDESEA_TaskInfoService/MesTaskService.cs"
index 308eac6..752fc07 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS/WMSServices/WIDESEA_TaskInfoService/MesTaskService.cs"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS/WMSServices/WIDESEA_TaskInfoService/MesTaskService.cs"
@@ -30,12 +30,19 @@
 using SqlSugar;
 using OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup;
 using WIDESEA_DTO.MES;
+using WIDESEA_External.Model;
+using System.Text.Json;
+using System.Text.RegularExpressions;
+using WIDESEA_Common.MaterielEnum;
+using MailKit.Search;
 
 namespace WIDESEA_TaskInfoService
 {
     public partial class TaskService
     {
-        static object lock_out = new object();
+        static object lock_autoIssue = new object();
+        static object lock_manualIssue = new object();
+        static object lock_returnIssue = new object();
         /// <summary>
         /// MES鑷姩鍙枡鎺ュ彛
         /// </summary>
@@ -45,46 +52,80 @@
             WebResponseContent content = new WebResponseContent();
             try
             {
-                if (autoIssueDTO == null)
+                lock (lock_autoIssue)
                 {
-                    return content.Error("浼犲叆淇℃伅涓嶈兘涓虹┖");
+                    if (autoIssueDTO == null)
+                    {
+                        return content.Error("浼犲叆淇℃伅涓嶈兘涓虹┖");
+                    }
+                    //鑾峰彇瀵瑰簲鍗曟嵁
+                    Dt_OutMESOrder? outMESOrder = _outboundRepository.OutMESOrderRepository.QueryFirst(x => x.OutDetailId == autoIssueDTO.OutDetailId);
+                    if (outMESOrder == null)
+                    {
+                        return content.Error($"棰嗘枡璁″垝{nameof(MESAutoIssueDTO.OutDetailId)}{autoIssueDTO.OutDetailId}涓嶅瓨鍦�");
+                    }
+                    if (outMESOrder.OutMESOrderStatus == OutOrderStatusEnum.鍑哄簱瀹屾垚.ObjToInt())
+                    {
+                        return content.Error($"棰嗘枡璁″垝{nameof(MESAutoIssueDTO.OutDetailId)}{outMESOrder.ProductOrderNo}宸ュ崟宸插嚭搴撳畬鎴�");
+                    }
+                    //鑾峰彇鍛ㄨ浆浣嶇疆缂栧彿
+                    Dt_AGVStationInfo? stationInfo = _basicRepository.AGVStationInfoRepository.QueryFirst(x => x.MESPointCode == autoIssueDTO.PointCode);
+                    if (stationInfo == null)
+                    {
+                        return content.Error($"棰嗘枡璁″垝鍛ㄨ浆浣峽nameof(MESAutoIssueDTO.PointCode)}{autoIssueDTO.PointCode}涓嶅瓨鍦�");
+                    }
+                    if (autoIssueDTO.IsEmptyPallet > 0)
+                    {
+                        return content.Error($"棰嗘枡璁″垝鍛ㄨ浆浣峽nameof(MESAutoIssueDTO.PointCode)}{autoIssueDTO.PointCode}瀛樺湪绌烘墭");
+                    }
+                    Dt_Task? task = BaseDal.QueryData(x => x.OrderNo == outMESOrder.OutMESOrderNo && x.TaskStatus == TaskStatusEnum.CallPending.ObjToInt()).OrderByDescending(x => x.Grade).ThenBy(x => x.TaskNum).FirstOrDefault();
+                    //鑾峰彇浠诲姟
+                    if (task == null)
+                    {
+                        return content.Error($"鏈壘鍒伴鏂欒鍒掔紪鍙穥outMESOrder.ProductOrderNo}鍙厤閫佷换鍔�");
+                    }
+                    //鑾峰彇浠诲姟鍑哄簱璇︽儏
+                    Dt_OutStockLockInfo outStockLockInfo = _outboundRepository.OutStockLockInfoRepository.QueryFirst(x => x.TaskNum == task.TaskNum);
+                    //璋冪敤MES閰嶉�佸嚭鍙戞寚浠�
+                    PlanDistributionInfo planDistribution = new PlanDistributionInfo()
+                    {
+                        DispatchPlanMaterialId = autoIssueDTO.OutDetailId,
+                        InvItemCode = task.MaterielCode,
+                        Quantity = outStockLockInfo.AssignQuantity,
+                        SendOutTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
+                        ArrivalTime = DateTime.Now.AddMinutes(15).ToString("yyyy-MM-dd HH:mm:ss")
+                    };
+                    MESDispatchModel dispatchModel = new MESDispatchModel()
+                    {
+                        PRO_DispachPlanDistributionInfos = new List<PlanDistributionInfo>() { planDistribution }
+                    };
+                    _unitOfWorkManage.BeginTran();
+                    task.TaskStatus = TaskStatusEnum.New.ObjToInt();
+                    task.TargetAddress = autoIssueDTO.PointCode.StartsWith("YS") ? stationInfo.AGVStationCode : autoIssueDTO.PointCode;
+                    BaseDal.UpdateData(task);
+                    MESResponse mESResponse = _invokeMESService.MESDispatchUp(dispatchModel).DeserializeObject<MESResponse>() ?? throw new Exception("鏈幏鍙栧埌杩斿洖淇℃伅");
+                    if (!mESResponse.Result)
+                    {
+                        throw new Exception($"MES閰嶉�佸嚭鍙戞帴鍙h皟鐢ㄦ姤閿�,MES杩斿洖淇℃伅{DecodeUnicode(mESResponse.Msg)}");
+                    }
+                    _unitOfWorkManage.CommitTran();
+                    PushTasksToWCS(new List<Dt_Task> { task });
+                    return content.OK("鍙枡鎴愬姛");
                 }
-                //鑾峰彇瀵瑰簲鍗曟嵁
-                Dt_OutMESOrder? outMESOrder = _outMESOrderRepository.QueryFirst(x=>x.OutDetailId==autoIssueDTO.OutDetailId);
-                if (outMESOrder==null)
-                {
-                    return content.Error($"棰嗘枡璁″垝{nameof(MESAutoIssueDTO.OutDetailId)}{autoIssueDTO.OutDetailId}涓嶅瓨鍦�");
-                }
-                if (outMESOrder.OutMESOrderStatus==OutOrderStatusEnum.鍏抽棴.ObjToInt())
-                {
-                    return content.Error($"棰嗘枡璁″垝{nameof(MESAutoIssueDTO.OutDetailId)}{outMESOrder.ProductOrderNo}宸ュ崟宸插叧闂�");
-                }
-                //鑾峰彇鍛ㄨ浆浣嶇疆缂栧彿
-                Dt_AGVStationInfo? stationInfo = _agvStationInfoRepository.QueryFirst(x=>x.MESPointCode==autoIssueDTO.PointCode);
-                if (stationInfo == null)
-                {
-                    return content.Error($"棰嗘枡璁″垝鍛ㄨ浆浣峽nameof(MESAutoIssueDTO.PointCode)}{autoIssueDTO.PointCode}涓嶅瓨鍦�");
-                }
-                if (autoIssueDTO.IsEmptyPallet>0)
-                {
-                    return content.Error($"棰嗘枡璁″垝鍛ㄨ浆浣峽nameof(MESAutoIssueDTO.PointCode)}{autoIssueDTO.PointCode}瀛樺湪绌烘墭");
-                }
-                //Dt_Task? task = BaseDal.QueryData(x => x.OrderNo == outMESOrder.OutMESOrderNo && x.TaskStatus==TaskStatusEnum.CallPending.ObjToInt()).OrderByDescending(x=>x.Grade).ThenBy(x=>x.TaskNum).FirstOrDefault();
-                ////鑾峰彇浠诲姟
-                //if (task==null)
-                //{
-                //    return content.Error($"鏈壘鍒伴鏂欒鍒掔紪鍙穥outMESOrder.ProductOrderNo}鍙厤閫佷换鍔�");
-                //}
-                //task.TaskStatus = TaskStatusEnum.New.ObjToInt();
-                //task.TargetAddress= stationInfo.AGVStationCode;
-                //PushTasksToWCS(new List<Dt_Task> { task });
-                return content.OK("鍙枡鎴愬姛");
             }
             catch (Exception ex)
             {
+                _unitOfWorkManage.RollbackTran();
                 content.Error(ex.Message);
             }
             return content;
+        }
+        //灏哢nicode瑙f瀽鎴愪腑鏂�
+        public static string DecodeUnicode(string input)
+        {
+            return Regex.Replace(input, @"\\u([0-9a-fA-F]{4})", match => {
+                return ((char)Convert.ToInt32(match.Groups[1].Value, 16)).ToString();
+            });
         }
 
         public WebResponseContent ReceiveManualIssue(MESManualIssueDTO manualIssueDTO)
@@ -92,36 +133,62 @@
             WebResponseContent content = new WebResponseContent();
             try
             {
-                if (manualIssueDTO == null)
+                lock (lock_manualIssue)
                 {
-                    return content.Error("浼犲叆淇℃伅涓嶈兘涓虹┖");
+                    if (manualIssueDTO == null)
+                    {
+                        return content.Error("浼犲叆淇℃伅涓嶈兘涓虹┖");
+                    }
+                    //鑾峰彇瀵瑰簲鍗曟嵁
+                    Dt_OutMESOrder? outMESOrder = _outboundRepository.OutMESOrderRepository.QueryFirst(x => x.OutDetailId == manualIssueDTO.OutDetailId);
+                    if (outMESOrder == null)
+                    {
+                        return content.Error($"棰嗘枡璁″垝{nameof(MESAutoIssueDTO.OutDetailId)}{manualIssueDTO.OutDetailId}涓嶅瓨鍦�");
+                    }
+                    if (outMESOrder.OutMESOrderStatus == OutOrderStatusEnum.鍏抽棴.ObjToInt())
+                    {
+                        return content.Error($"棰嗘枡璁″垝{nameof(MESAutoIssueDTO.OutDetailId)}{outMESOrder.ProductOrderNo}宸ュ崟宸插叧闂�");
+                    }
+                    //鑾峰彇鍛ㄨ浆浣嶇疆缂栧彿
+                    Dt_AGVStationInfo? stationInfo = _basicRepository.AGVStationInfoRepository.QueryFirst(x => x.MESPointCode == manualIssueDTO.PointCode);
+                    if (stationInfo == null)
+                    {
+                        return content.Error($"棰嗘枡璁″垝鍛ㄨ浆浣峽nameof(MESAutoIssueDTO.PointCode)}{manualIssueDTO.PointCode}涓嶅瓨鍦�");
+                    }
+                    Dt_Task? task = BaseDal.QueryData(x => x.OrderNo == outMESOrder.OutMESOrderNo && x.TaskStatus == TaskStatusEnum.CallPending.ObjToInt()).OrderByDescending(x => x.Grade).ThenBy(x => x.TaskNum).FirstOrDefault();
+                    //鑾峰彇浠诲姟
+                    if (task == null)
+                    {
+                        return content.Error($"鏈壘鍒伴鏂欒鍒掔紪鍙穥outMESOrder.ProductOrderNo}鍙厤閫佷换鍔�");
+                    }
+                    //鑾峰彇浠诲姟鍑哄簱璇︽儏
+                    Dt_OutStockLockInfo outStockLockInfo = _outboundRepository.OutStockLockInfoRepository.QueryFirst(x => x.TaskNum == task.TaskNum);
+                    //璋冪敤MES閰嶉�佸嚭鍙戞寚浠�
+                    PlanDistributionInfo planDistribution = new PlanDistributionInfo()
+                    {
+                        DispatchPlanMaterialId = manualIssueDTO.OutDetailId,
+                        InvItemCode = task.MaterielCode,
+                        Quantity = outStockLockInfo.AssignQuantity,
+                        SendOutTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
+                        ArrivalTime = DateTime.Now.AddMinutes(15).ToString("yyyy-MM-dd HH:mm:ss")
+                    };
+                    MESDispatchModel dispatchModel = new MESDispatchModel()
+                    {
+                        PRO_DispachPlanDistributionInfos = new List<PlanDistributionInfo>() { planDistribution }
+                    };
+                    _unitOfWorkManage.BeginTran();
+                    task.TaskStatus = TaskStatusEnum.New.ObjToInt();
+                    task.TargetAddress = manualIssueDTO.PointCode.StartsWith("YS") ? stationInfo.AGVStationCode : manualIssueDTO.PointCode;
+                    BaseDal.UpdateData(task);
+                    MESResponse mESResponse = _invokeMESService.MESDispatchUp(dispatchModel).DeserializeObject<MESResponse>() ?? throw new Exception("鏈幏鍙栧埌杩斿洖淇℃伅");
+                    if (!mESResponse.Result)
+                    {
+                        throw new Exception($"MES閰嶉�佸嚭鍙戞帴鍙h皟鐢ㄦ姤閿�,MES杩斿洖淇℃伅{DecodeUnicode(mESResponse.Msg)}");
+                    }
+                    _unitOfWorkManage.CommitTran();
+                    PushTasksToWCS(new List<Dt_Task> { task });
+                    return content.OK("鍙枡鎴愬姛");
                 }
-                //鑾峰彇瀵瑰簲鍗曟嵁
-                Dt_OutMESOrder? outMESOrder = _outMESOrderRepository.QueryFirst(x => x.OutDetailId == manualIssueDTO.OutDetailId);
-                if (outMESOrder == null)
-                {
-                    return content.Error($"棰嗘枡璁″垝{nameof(MESAutoIssueDTO.OutDetailId)}{manualIssueDTO.OutDetailId}涓嶅瓨鍦�");
-                }
-                if (outMESOrder.OutMESOrderStatus == OutOrderStatusEnum.鍏抽棴.ObjToInt())
-                {
-                    return content.Error($"棰嗘枡璁″垝{nameof(MESAutoIssueDTO.OutDetailId)}{outMESOrder.ProductOrderNo}宸ュ崟宸插叧闂�");
-                }
-                //鑾峰彇鍛ㄨ浆浣嶇疆缂栧彿
-                Dt_AGVStationInfo? stationInfo = _agvStationInfoRepository.QueryFirst(x => x.MESPointCode == manualIssueDTO.PointCode);
-                if (stationInfo == null)
-                {
-                    return content.Error($"棰嗘枡璁″垝鍛ㄨ浆浣峽nameof(MESAutoIssueDTO.PointCode)}{manualIssueDTO.PointCode}涓嶅瓨鍦�");
-                }
-                //Dt_Task? task = BaseDal.QueryData(x => x.OrderNo == outMESOrder.OutMESOrderNo && x.TaskStatus == TaskStatusEnum.CallPending.ObjToInt()).OrderByDescending(x => x.Grade).ThenBy(x => x.TaskNum).FirstOrDefault();
-                ////鑾峰彇浠诲姟
-                //if (task == null)
-                //{
-                //    return content.Error($"鏈壘鍒伴鏂欒鍒掔紪鍙穥outMESOrder.ProductOrderNo}鍙厤閫佷换鍔�");
-                //}
-                //task.TaskStatus = TaskStatusEnum.New.ObjToInt();
-                //task.TargetAddress = stationInfo.AGVStationCode;
-                //PushTasksToWCS(new List<Dt_Task> { task });
-                return content.OK("鍙枡鎴愬姛");
             }
             catch (Exception ex)
             {
@@ -129,31 +196,139 @@
             }
             return content;
         }
-
+        /// <summary>
+        /// MES绌烘墭/浣欐枡鍛煎彨鎺ュ彛
+        /// </summary>
+        /// <returns></returns>
         public WebResponseContent ReceiveReturnIssue(List<MESReturnIssueDTO> returnIssueDTOs)
         {
             WebResponseContent content = new WebResponseContent();
             try
             {
-                if (returnIssueDTOs==null || returnIssueDTOs.Count<=0)
+                lock (lock_returnIssue)
                 {
-                    return content.Error("浼犲叆淇℃伅涓嶈兘涓虹┖");
+                    if (returnIssueDTOs == null || returnIssueDTOs.Count <= 0)
+                    {
+                        return content.Error("浼犲叆淇℃伅涓嶈兘涓虹┖");
+                    }
+                    //鑾峰彇鎵�鏈堿GV鐐逛綅
+                    List<Dt_AGVStationInfo> aGVStationInfos = _basicRepository.AGVStationInfoRepository.QueryData(x => !string.IsNullOrEmpty(x.MESPointCode));
+                    MESReturnIssueDTO? returnIssueDTO = returnIssueDTOs.FirstOrDefault(x => !aGVStationInfos.Select(x => x.MESPointCode).Contains(x.PointCode));
+                    if (returnIssueDTO != null)
+                    {
+                        return content.Error($"鍛ㄨ浆浣峽nameof(MESReturnIssueDTO.PointCode)}{returnIssueDTO.PointCode}涓嶅瓨鍦�");
+                    }
+                    //鑾峰彇鎵�鏈夊簱瀛�
+                    List<Dt_StockInfo> stockInfosOld = _stockRepository.StockInfoRepository.QueryData();
+                    ////绌烘墭
+                    //foreach (var item in returnIssueDTOs.Where(x=>x.ReturnMaterial==null))
+                    //{
+
+                    //}
+                    //閫�鏂�
+                    List<Dt_StockInfo> stockInfos=new List<Dt_StockInfo>();
+                    List<Dt_Task> tasksNew = new List<Dt_Task>();
+                    foreach (var item in returnIssueDTOs.Where(x => x.ReturnMaterial != null))
+                    {
+                        MESReturnMaterial? returnMaterial = item.ReturnMaterial;
+                        if (returnMaterial.BarCode.IsNullOrEmpty())
+                        {
+                            return content.Error($"閫�鏂欎紶鍏ユ潯鐮佷笉鑳戒负绌�");
+                        }
+
+                        Dt_AGVStationInfo aGVStationInfo = aGVStationInfos.FirstOrDefault(x => x.MESPointCode == item.PointCode);
+                        Dt_MaterielInfo? materielInfo = _basicRepository.MaterielInfoRepository.QueryFirst(x => x.MaterielCode == returnMaterial.MaterialCode);
+                        if (materielInfo == null)
+                        {
+                            return content.Error($"鏈壘鍒版潯鐮亄returnMaterial.BarCode}鐗╂枡淇℃伅");
+                        }
+                        //鍒ゆ柇
+                        if (returnMaterial.Thickness <= 0 && materielInfo.WarehouseId==WarehouseEnum.LLDYL.ObjToInt())
+                        {
+                            return content.Error($"鐗╂枡{returnMaterial.MaterialCode}鏉$爜{returnMaterial.BarCode}鐩村緞涓嶈兘灏忎簬0");
+                        }
+                        if (returnMaterial.Wide <= 0 && materielInfo.WarehouseId == WarehouseEnum.LLDYL.ObjToInt())
+                        {
+                            return content.Error($"鐗╂枡{returnMaterial.MaterialCode}鏉$爜{returnMaterial.BarCode}鐩村緞涓嶈兘灏忎簬0");
+                        }
+                        Dt_StockInfo? stockInfoOld = stockInfosOld.FirstOrDefault(x => x.PalletCode == returnMaterial.BarCode);
+                        if (stockInfoOld != null)
+                        {
+                            return content.Error($"鏉$爜{returnMaterial.BarCode}淇℃伅宸插瓨鍦�");
+                        }
+                        //鐢熸垚搴撳瓨缁勭洏淇℃伅
+                        Dt_StockInfo stockInfo = new Dt_StockInfo()
+                        {
+                            MaterielInvOrgId = materielInfo.MaterielInvOrgId,
+                            PalletCode = returnMaterial.BarCode,
+                            LocationCode = "",
+                            PalletType = 1,
+                            WarehouseId = materielInfo.WarehouseId,
+                            StockAttribute = materielInfo.MaterielSourceType,
+                            StockStatus = StockStatusEmun.MES浣欐枡閫�搴�.ObjToInt(),
+                            MaterielSpec = materielInfo.MaterielSpec,
+                            BatchNo = returnMaterial.MaterialLot,
+                            Unit = materielInfo.MaterielUnit,
+                            MaterielThickness = returnMaterial.Thickness,
+                            CheckThickness= returnMaterial.Thickness,
+                            MaterielWide = returnMaterial.Wide,
+                            MaterielWeight = returnMaterial.Weight,
+                            MaterielCode = materielInfo.MaterielCode,
+                            StockLength = returnMaterial.ReturnQuantity,
+                            OrderNo = returnMaterial.ReturnOrderNo,
+                            MaterielName = materielInfo.MaterielName,
+                            IsFull = WhetherEnum.True.ObjToInt(),
+                            IsPick = returnMaterial.Whether == 0 ? WhetherEnum.True.ObjToInt() : WhetherEnum.False.ObjToInt(),
+                            Remark = StockStatusEmun.MES浣欐枡閫�搴�.ToString()
+                        };
+                        if (stockInfo.MaterielWide > 1200)
+                        {
+                            stockInfo.PalletType = 2;
+                        }
+                        stockInfos.Add(stockInfo);
+                        //鐢熸垚浣欐枡閫�鏂欎换鍔�
+                        Dt_Task newTask = new Dt_Task()
+                        {
+                            CurrentAddress = item.PointCode.StartsWith("YS") ? aGVStationInfo.AGVStationCode : item.PointCode,
+                            Grade = 0,
+                            NextAddress = "",
+                            PalletCode = stockInfo.PalletCode,
+                            Roadway = "",
+                            SourceAddress = item.PointCode.StartsWith("YS") ? aGVStationInfo.AGVStationCode : item.PointCode,
+                            TargetAddress = "",
+                            TaskStatus = TaskStatusEnum.New.ObjToInt(),
+                            WarehouseId = materielInfo.WarehouseId,
+                            PalletType = stockInfo.PalletType,
+                            MaterielCode=stockInfo.MaterielCode,
+                            Quantity=stockInfo.StockLength,
+                            OrderNo=stockInfo.OrderNo,
+                            TaskLength = (int)stockInfo.MaterielWide,
+                            GroupId= item.IssueId,
+                            WorkCentreCode=item.MakeCode
+                        };
+                        TaskTypeEnum taskTypeEnum = aGVStationInfo.StationArea switch
+                        {
+                            nameof(StationAreaEnum.涓�妤煎嵃鍒�) => TaskTypeEnum.PrintYLBackInbound,
+                            _ => throw new Exception("鏈壘鍒板搴斾换鍔�")
+                        };
+                        newTask.TaskType = taskTypeEnum.ObjToInt();
+                        tasksNew.Add(newTask);
+                    }
+                    _unitOfWorkManage.BeginTran();
+                    BaseDal.AddData(tasksNew);
+                    _stockRepository.StockInfoRepository.AddData(stockInfos);
+                    _unitOfWorkManage.CommitTran();
+                    //鎺ㄩ�佷换鍔�
+                    PushTasksToWCS(tasksNew);
+                    content.OK("鍛煎彨鎴愬姛");
                 }
-                //鑾峰彇鎵�鏈堿GV鐐逛綅
-                List<Dt_AGVStationInfo> aGVStationInfos= _agvStationInfoRepository.QueryData(x => !string.IsNullOrEmpty(x.MESPointCode));
-                MESReturnIssueDTO? returnIssueDTO = returnIssueDTOs.FirstOrDefault(x=> !aGVStationInfos.Select(x=>x.MESPointCode).Contains(x.PointCode));
-                if (returnIssueDTO != null)
-                {
-                    return content.Error($"鍛ㄨ浆浣峽nameof(MESReturnIssueDTO.PointCode)}{returnIssueDTO.PointCode}涓嶅瓨鍦�");
-                }
-                content.OK("鍛煎彨鎴愬姛");
             }
             catch (Exception ex)
             {
+                _unitOfWorkManage.RollbackTran();
                 content.Error(ex.Message);
             }
             return content;
         }
-        
     }
 }

--
Gitblit v1.9.3