dengjunjie
3 天以前 b784d019c3848718eb95eb0d34dde34c6a262b06
´úÂë¹ÜÀí/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_BasicInfoService/BoxingDetailService.cs
@@ -3,12 +3,18 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using WIDESEAWCS_Common;
using WIDESEAWCS_Common.PLCEnum;
using WIDESEAWCS_Core;
using WIDESEAWCS_Core.BaseRepository;
using WIDESEAWCS_Core.BaseServices;
using WIDESEAWCS_Core.Helper;
using WIDESEAWCS_DTO.BasicInfo;
using WIDESEAWCS_IBasicInfoService;
using WIDESEAWCS_Model.Models;
using WIDESEAWCS_QuartzJob;
namespace WIDESEAWCS_BasicInfoService
{
@@ -18,6 +24,10 @@
        private readonly IBoxingService _boxingService;
        private readonly IFormulaService _formulaService;
        private readonly IFormulaDetailService _formulaDetailService;
        private readonly IProcessInfoDetailService _processInfoDetailService;
        private readonly IScanStationService _scanStationService;
        private readonly IUnitOfWorkManage _unitOfWorkManage;
        public BoxingDetailService(
@@ -25,13 +35,18 @@
            IFormulaService formulaService,
            IBoxingService boxingService,
            IFormulaDetailService formulaDetailService,
            IProcessInfoDetailService processInfoDetailService,
            IScanStationService scanStationService,
            IUnitOfWorkManage unitOfWorkManage
            ) : base(BaseDal)
        {
            _formulaService = formulaService;
            _boxingService = boxingService;
            _formulaDetailService = formulaDetailService;
            _processInfoDetailService = processInfoDetailService;
            _scanStationService = scanStationService;
            _unitOfWorkManage = unitOfWorkManage;
        }
        public IRepository<Dt_BoxingDetail> Repository => BaseDal;
@@ -39,18 +54,55 @@
        /// <summary>
        /// æ¯”较零件是否齐全
        /// </summary>
        /// <param name="boxingDetails"></param>
        /// <param name="formulaDetails"></param>
        /// <returns></returns>
        public bool IsComponentCodesEqual(List<Dt_BoxingDetail> boxingDetails, List<Dt_FormulaDetail> formulaDetails)
        /// <param name="boxingDetails">实际装箱的零件集合</param>
        /// <param name="formulaDetails">配方要求的零件集合</param>
        /// <returns>是否完全匹配</returns>
        public bool CheckComponentsMatchExactly(List<string> boxingDetails, List<string> formulaDetails)
        {
            // 1. åŸºç¡€æ ¡éªŒï¼šç©ºå€¼/数量不一致直接返回不匹配
            if (boxingDetails == null || formulaDetails == null || boxingDetails.Count != formulaDetails.Count)
            {
                return false;
            }
            List<string> BoxingIdList = boxingDetails.Select(x => x.ComponentCode).ToList();
            List<string> FormulaIdList = formulaDetails.Select(x => x.ComponentCode).ToList();
            return !BoxingIdList.Except(FormulaIdList).Any() && !FormulaIdList.Except(BoxingIdList).Any();
            // 2. ä¸¤ä¸ªç©ºé›†åˆç›´æŽ¥åˆ¤å®šä¸ºåŒ¹é…ï¼ˆæ— é›¶ä»¶=零件齐全)
            if (boxingDetails.Count == 0)
            {
                return true;
            }
            // 3. ç»Ÿè®¡ç¬¬ä¸€ä¸ªé›†åˆçš„元素出现次数(严格键匹配,处理重复元素)
            var elementCountDict = new Dictionary<string, int>();
            foreach (var item in boxingDetails)
            {
                // å¤„理集合中的null元素,转为空字符串避免字典键为null报错
                var key = item ?? string.Empty;
                if (elementCountDict.ContainsKey(key))
                {
                    elementCountDict[key]++;
                }
                else
                {
                    elementCountDict[key] = 1;
                }
            }
            // 4. éåŽ†ç¬¬äºŒä¸ªé›†åˆï¼ŒæŠµæ¶ˆè®¡æ•°ï¼šæ— æ­¤å…ƒç´ /数量不匹配直接返回false
            foreach (var item in formulaDetails)
            {
                var key = item ?? string.Empty;
                if (!elementCountDict.ContainsKey(key))
                {
                    return false; // å­˜åœ¨é…æ–¹æ²¡æœ‰/装箱多出来的零件
                }
                elementCountDict[key]--;
                if (elementCountDict[key] == 0)
                {
                    elementCountDict.Remove(key); // è®¡æ•°æ¸…零则移除,避免干扰最终判断
                }
            }
            // 5. å­—典为空 = æ‰€æœ‰å…ƒç´ ç§ç±»+数量完全匹配
            return elementCountDict.Count == 0;
        }
@@ -62,6 +114,7 @@
        /// <returns></returns>
        public string IsComponentCodesEqual(List<string> boxingDetails, List<string> formulaDetails)
        {
            // å¤„理null集合,规避空指针异常
            var boxList = boxingDetails ?? new List<string>();
            var formulaList = formulaDetails ?? new List<string>();
@@ -100,134 +153,222 @@
                    {
                        return WebResponseContent.Instance.Error("提交参数不能为空");
                    }
                    string palletCode = toolingBoardSubmitDto.ToolingBoardNo?.Trim();
                    string productCode = toolingBoardSubmitDto.FinishedProductCode?.Trim();
                    if (string.IsNullOrWhiteSpace(palletCode))
                    {
                        return WebResponseContent.Instance.Error("工装板编号不能为空");
                    }
                    if (string.IsNullOrWhiteSpace(productCode))
                    {
                        return WebResponseContent.Instance.Error("成品编码不能为空");
                    }
                    string productCode = toolingBoardSubmitDto.FinishedProductCode.Trim();
                    // 2. æŸ¥è¯¢æˆå“é…æ–¹ä¿¡æ¯
                    Dt_Formula formulaModel = _formulaService.Repository.QueryFirst(x => x.ProductCode == productCode);
                    if (formulaModel == null)
                    {
                        return WebResponseContent.Instance.Error("无成品配方,请核对成品编码");
                    }
                    string proCode = string.Empty;
                    string proOther = string.Empty;
                    string supplierCode = string.Empty;
                    List<Dt_FormulaDetail> dt_FormulaDetails = _formulaDetailService.Repository.QueryData(x => x.FormulaId == formulaModel.Id && x.IsScanned == 1);
                    List<string> Codelist = dt_FormulaDetails.Select(x => x.ComponentCode).ToList();
                    string IsCode = IsComponentCodesEqual(toolingBoardSubmitDto.PartsList, Codelist);
                    if (IsCode != null)
                    if (!string.IsNullOrWhiteSpace(productCode))
                    {
                        return WebResponseContent.Instance.Error($"物料【{IsCode}】错误,请核对物料编号");
                    }
                    // 3. æ ¸å¿ƒåˆ¤æ–­ï¼šæ ¹æ®å·¥è£…板编号查询是否存在【新增/修改】的主表数据
                    Dt_Boxing existBoxinModel = _boxingService.Repository.QueryFirst(x => x.PalletCode == palletCode);
                    if (existBoxinModel == null)
                    {
                        #region æ–°å¢žé€»è¾‘ - åŽŸé€»è¾‘ä¼˜åŒ–ç‰ˆ
                        Dt_Boxing dt_boxin = new Dt_Boxing()
                        var proCodeMatch = Regex.Match(productCode, @"TX(\d+)(?=\s|\||$)", RegexOptions.IgnoreCase);
                        if (proCodeMatch.Success)
                        {
                            PalletCode = palletCode,
                            ProductCode = productCode,
                            ProductName = formulaModel.ProductName.Trim(),
                            Creater = "admin",
                            CreateDate = DateTime.Now
                        };
                        int newBoxingId = _boxingService.Repository.AddData(dt_boxin);
                        // æ‰¹é‡æ·»åŠ æ˜Žç»†è¡¨æ•°æ®
                        if (toolingBoardSubmitDto.PartsList != null && toolingBoardSubmitDto.PartsList.Count > 0)
                        {
                            List<Dt_BoxingDetail> detailList = new List<Dt_BoxingDetail>();
                            foreach (string ComponentCode in toolingBoardSubmitDto.PartsList)
                            {
                                if (string.IsNullOrWhiteSpace(ComponentCode)) continue;
                                string ComponentCodeTrim = ComponentCode.Trim();
                                Dt_FormulaDetail formulaDetail = _formulaDetailService.Repository.QueryFirst(x => x.FormulaId == formulaModel.Id && x.ComponentCode == ComponentCodeTrim);
                                if (formulaDetail == null)
                                {
                                    return WebResponseContent.Instance.Error($"配方中无此物料【{ComponentCodeTrim}】,请核对物料编号");
                                }
                                Dt_BoxingDetail detailModel = new Dt_BoxingDetail()
                                {
                                    BoxingId = newBoxingId,
                                    ComponentCode = ComponentCodeTrim,
                                    ComponentName = formulaDetail.ComponentName,
                                    Creater = "admin",
                                    CreateDate = DateTime.Now
                                };
                                detailList.Add(detailModel);
                            }
                            if (detailList.Count > 0)
                            {
                                BaseDal.AddData(detailList);
                            }
                        }
                        #endregion
                    }
                    else
                    {
                        #region ä¿®æ”¹é€»è¾‘ - æ–°å¢žæ ¸å¿ƒé€»è¾‘
                        // 1. æ›´æ–°ä¸»è¡¨æ•°æ®
                        existBoxinModel.ProductCode = productCode;
                        existBoxinModel.ProductName = formulaModel.ProductName.Trim();
                         existBoxinModel.Modifier = "admin";
                        existBoxinModel.ModifyDate = DateTime.Now;
                        _boxingService.Repository.UpdateData(existBoxinModel);
                        int boxingId = existBoxinModel.Id;
                        // 2. åˆ é™¤è¯¥ç»„盘下的【原有全部明细表数据】
                        List<Dt_BoxingDetail> oldDetailList = BaseDal.QueryData(x => x.BoxingId == boxingId);
                        if (oldDetailList != null && oldDetailList.Count > 0)
                        {
                            BaseDal.DeleteData(oldDetailList);
                            proCode = $"TX{proCodeMatch.Groups[1].Value.Trim()}";
                        }
                        // 3. é‡æ–°æ’入修改后的明细表数据
                        if (toolingBoardSubmitDto.PartsList != null && toolingBoardSubmitDto.PartsList.Count > 0)
                        // æ­£åˆ™2:匹配连续的10位纯数字(全局匹配,取第一个符合的即可)
                        var proOtherMatch = Regex.Match(productCode, @"\d{10}");
                        if (proOtherMatch.Success)
                        {
                            List<Dt_BoxingDetail> detailList = new List<Dt_BoxingDetail>();
                            foreach (string ComponentCode in toolingBoardSubmitDto.PartsList)
                            {
                                if (string.IsNullOrWhiteSpace(ComponentCode)) continue;
                                string ComponentCodeTrim = ComponentCode.Trim();
                                Dt_FormulaDetail formulaDetail = _formulaDetailService.Repository.QueryFirst(x => x.FormulaId == formulaModel.Id && x.ComponentCode == ComponentCodeTrim);
                                if (formulaDetail == null)
                                {
                                    return WebResponseContent.Instance.Error($"配方中无此物料【{ComponentCodeTrim}】,请核对物料名称");
                                }
                                Dt_BoxingDetail detailModel = new Dt_BoxingDetail()
                                {
                                    BoxingId = boxingId,
                                    ComponentCode = ComponentCodeTrim,
                                    ComponentName = formulaDetail.ComponentName,
                                    Creater = "admin",
                                    CreateDate = DateTime.Now
                                };
                                detailList.Add(detailModel);
                            }
                            if (detailList.Count > 0)
                            {
                                BaseDal.AddData(detailList);
                            }
                            proOther = proOtherMatch.Value.Trim();
                        }
                        #endregion
                        var supplierCodeMatch = Regex.Match(productCode, @"[A-Z]+$", RegexOptions.IgnoreCase);
                        if (supplierCodeMatch.Success)
                        {
                            supplierCode = supplierCodeMatch.Value.Trim();
                        }
                        toolingBoardSubmitDto.PartsList = toolingBoardSubmitDto.PartsList.Where(code => !string.IsNullOrEmpty(code)).ToList();
                        // 2. æŸ¥è¯¢æˆå“é…æ–¹ä¿¡æ¯
                        Dt_Formula formulaModel = _formulaService.Repository.QueryFirst(x => x.ProductCode == proCode);
                        if (formulaModel == null)
                        {
                            return WebResponseContent.Instance.Error("无成品配方,请核对成品编码");
                        }
                        Dt_ScanStation dt_ScanStation = _scanStationService.Repository.QueryFirst(x => x.StationCode == "001");
                        if (dt_ScanStation.StationEndProduct != proCode)
                        {
                            return WebResponseContent.Instance.Error("成品编号错误");
                        }
                        List<Dt_FormulaDetail> dt_FormulaDetails = _formulaDetailService.Repository.QueryData(x => x.FormulaId == formulaModel.Id && x.IsScanned == 1);
                        List<string> Codelist = dt_FormulaDetails.Select(x => x.ComponentCode).ToList();
                        string IsCode = IsComponentCodesEqual(toolingBoardSubmitDto.PartsList, Codelist);
                        if (IsCode != null)
                        {
                            return WebResponseContent.Instance.Error($"物料【{IsCode}】错误,请核对物料编号");
                        }
                        //Dt_Boxing existBoxinModel = _boxingService.Repository.QueryFirst(x => x.PalletCode == PalletCode);
                        //if (existBoxinModel == null)
                        //{
                        //    return WebResponseContent.Instance.Error($"托盘未添加,请稍后重试");
                        //}
                        if (!CheckComponentsMatchExactly(toolingBoardSubmitDto.PartsList, Codelist))
                        {
                            throw new InvalidOperationException("零件与配方表中不同");
                        }
                        var PalletCode = TcpClientExample.Start("192.168.2.120", 2001);
                        if (!PalletCode.IsNotEmptyOrNull() || PalletCode == "NoRead")
                        {
                            throw new InvalidOperationException("托盘码未扫到,请重试");
                        }
                        Dt_Boxing dt_Boxing = _boxingService.Repository.QueryFirst(x => x.PalletCode == PalletCode);
                        if (dt_Boxing != null)
                        {
                            throw new InvalidOperationException("托盘码重复扫描");
                        }
                        Dt_Boxing existBoxinModel = new Dt_Boxing();
                        existBoxinModel.PalletCode = PalletCode;
                        existBoxinModel.ProductCode = proCode;
                        existBoxinModel.BoxingNo = proOther;
                        existBoxinModel.SupplierCode = supplierCode;
                        int id = _boxingService.Repository.AddData(existBoxinModel);
                        foreach (var item in dt_FormulaDetails)
                        {
                            Dt_BoxingDetail dt_BoxingDetail = new Dt_BoxingDetail()
                            {
                                BoxingId = id,
                                ComponentCode = item.ComponentCode,
                                ComponentName = item.ComponentName,
                                Creater = "admin",
                                CreateDate = new DateTime()
                            };
                            BaseDal.AddData(dt_BoxingDetail);
                        }
                        uow.Commit();
                    }
                    uow.Commit();
                    string msg = existBoxinModel == null ? "组盘信息新增成功!" : "组盘信息修改成功!";
                    OtherDevice? device = Storage.Devices.FirstOrDefault(x => x.DeviceName == "主控PLC") as OtherDevice;
                    if (device == null) throw new Exception("未找到主控PLC设备信息");
                    if (!device.IsConnected) throw new Exception($"主控PLC设备通讯异常");
                    device.SetValue(W_PLCDBName.wboolLocation5ScanDone, true);
                    Thread.Sleep(500);
                    device.SetValue(W_PLCDBName.wboolLocation5ScanDone, false);
                    //    if (existBoxinModel == null)
                    //{
                    //    #region æ–°å¢žé€»è¾‘ - åŽŸé€»è¾‘ä¼˜åŒ–ç‰ˆ
                    //    Dt_Boxing dt_boxin = new Dt_Boxing()
                    //    {
                    //        PalletCode = palletCode,
                    //        ProductCode = productCode,
                    //        ProductName = formulaModel.ProductName.Trim(),
                    //        Creater = "admin",
                    //        CreateDate = DateTime.Now
                    //    };
                    //    int newBoxingId = _boxingService.Repository.AddData(dt_boxin);
                    //    // æ‰¹é‡æ·»åŠ æ˜Žç»†è¡¨æ•°æ®
                    //    if (toolingBoardSubmitDto.PartsList != null && toolingBoardSubmitDto.PartsList.Count > 0)
                    //    {
                    //        List<Dt_BoxingDetail> detailList = new List<Dt_BoxingDetail>();
                    //        foreach (string ComponentCode in toolingBoardSubmitDto.PartsList)
                    //        {
                    //            if (string.IsNullOrWhiteSpace(ComponentCode)) continue;
                    //            string ComponentCodeTrim = ComponentCode.Trim();
                    //            Dt_FormulaDetail formulaDetail = _formulaDetailService.Repository.QueryFirst(x => x.FormulaId == formulaModel.Id && x.ComponentCode == ComponentCodeTrim);
                    //            if (formulaDetail == null)
                    //            {
                    //                return WebResponseContent.Instance.Error($"配方中无此物料【{ComponentCodeTrim}】,请核对物料编号");
                    //            }
                    //            Dt_BoxingDetail detailModel = new Dt_BoxingDetail()
                    //            {
                    //                BoxingId = newBoxingId,
                    //                ComponentCode = ComponentCodeTrim,
                    //                ComponentName = formulaDetail.ComponentName,
                    //                Creater = "admin",
                    //                CreateDate = DateTime.Now
                    //            };
                    //            detailList.Add(detailModel);
                    //        }
                    //        if (detailList.Count > 0)
                    //        {
                    //            BaseDal.AddData(detailList);
                    //        }
                    //    }
                    //    #endregion
                    //}
                    //else
                    //{
                    //    #region ä¿®æ”¹é€»è¾‘ - æ–°å¢žæ ¸å¿ƒé€»è¾‘
                    //    // 1. æ›´æ–°ä¸»è¡¨æ•°æ®
                    //    existBoxinModel.ProductCode = productCode;
                    //    existBoxinModel.ProductName = formulaModel.ProductName.Trim();
                    //     existBoxinModel.Modifier = "admin";
                    //    existBoxinModel.ModifyDate = DateTime.Now;
                    //    _boxingService.Repository.UpdateData(existBoxinModel);
                    //    int boxingId = existBoxinModel.Id;
                    //    // 2. åˆ é™¤è¯¥ç»„盘下的【原有全部明细表数据】
                    //    List<Dt_BoxingDetail> oldDetailList = BaseDal.QueryData(x => x.BoxingId == boxingId);
                    //    if (oldDetailList != null && oldDetailList.Count > 0)
                    //    {
                    //        BaseDal.DeleteData(oldDetailList);
                    //    }
                    //    // 3. é‡æ–°æ’入修改后的明细表数据
                    //    if (toolingBoardSubmitDto.PartsList != null && toolingBoardSubmitDto.PartsList.Count > 0)
                    //    {
                    //        List<Dt_BoxingDetail> detailList = new List<Dt_BoxingDetail>();
                    //        foreach (string ComponentCode in toolingBoardSubmitDto.PartsList)
                    //        {
                    //            if (string.IsNullOrWhiteSpace(ComponentCode)) continue;
                    //            string ComponentCodeTrim = ComponentCode.Trim();
                    //            Dt_FormulaDetail formulaDetail = _formulaDetailService.Repository.QueryFirst(x => x.FormulaId == formulaModel.Id && x.ComponentCode == ComponentCodeTrim);
                    //            if (formulaDetail == null)
                    //            {
                    //                return WebResponseContent.Instance.Error($"配方中无此物料【{ComponentCodeTrim}】,请核对物料名称");
                    //            }
                    //            Dt_BoxingDetail detailModel = new Dt_BoxingDetail()
                    //            {
                    //                BoxingId = boxingId,
                    //                ComponentCode = ComponentCodeTrim,
                    //                ComponentName = formulaDetail.ComponentName,
                    //                Creater = "admin",
                    //                CreateDate = DateTime.Now
                    //            };
                    //            detailList.Add(detailModel);
                    //        }
                    //        if (detailList.Count > 0)
                    //        {
                    //            BaseDal.AddData(detailList);
                    //        }
                    //    }
                    //    #endregion
                    //}
                    //uow.Commit();
                    string msg = null;
                    List<Dt_ProcessInfoDetail> dt_ProcessInfoDetail = _processInfoDetailService.Repository
                            .QueryData(x => x.ProductSn == proOther && x.ProductCode == proCode).ToList();
                    // 3. åˆ¤æ–­æŸ¥è¯¢ç»“果,存在则赋值提示信息
                    if (dt_ProcessInfoDetail.Count <= 3 && dt_ProcessInfoDetail.Count != 0)
                    {
                        msg = "已有流水号";
                    }
                    // 4. è¿”回响应(存在重复则msg是"已有流水号",不存在则msg为null)
                    return WebResponseContent.Instance.OK(msg);
                }
                catch (Exception ex)