pan
2025-11-05 b2c6ce78c7c95c37f9c3e9ea11e86a7af7b0d3fd
提交
已添加13个文件
已修改25个文件
2249 ■■■■ 文件已修改
项目代码/WMS无仓储版/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/CopilotIndices/17.14.878.3237/CodeChunks.db 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/CopilotIndices/17.14.878.3237/CodeChunks.db-shm 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/CopilotIndices/17.14.878.3237/CodeChunks.db-wal 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/CopilotIndices/17.14.878.3237/SemanticSymbols.db 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/CopilotIndices/17.14.878.3237/SemanticSymbols.db-shm 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/CopilotIndices/17.14.878.3237/SemanticSymbols.db-wal 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_AllocateService/AllocateService.cs 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_AllocateService/WIDESEA_AllocateService.csproj 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_BasicService/DailySequenceService.cs 245 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_BasicService/ESSApiService.cs 40 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_BasicService/ErpApiService.cs 379 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_BasicService/InvokeMESService.cs 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_BasicService/LocationInfoService.cs 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_BasicService/MaterialUnitService.cs 168 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_Common/LocationEnum/LocationStatusEnum.cs 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_Common/OrderEnum/InboundOrderMenu.cs 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_Common/TaskEnum/TaskTypeEnum.cs 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_DTO/Allocate/AllocateDto.cs 139 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_IAllocateService/IAllocateService.cs 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_IAllocateService/WIDESEA_IAllocateService.csproj 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_IBasicService/IDailySequenceService.cs 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_IBasicService/IMaterialUnitService.cs 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_ITaskInfoService/ITaskService.cs 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_InboundService/InboundOrderService.cs 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_Model/Models/Allocate/Dt_ AllocateOrder.cs 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_Model/Models/Allocate/Dt_AllocateOrderDetail.cs 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_Model/Models/Basic/DT_DailySequence.cs 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_Model/Models/Stock/Dt_StockInfoDetail.cs 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_Model/Models/TaskInfo/Dt_Task.cs 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundOrderService.cs 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService.cs 463 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService_Inbound.cs 233 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService_Outbound.cs 126 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_WMSServer.sln 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Allocate/AllocateOrderController.cs 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/ESSController.cs 88 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Inbound/InboundOrderController.cs 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_WMSServer/WIDESEA_WMSServer.csproj 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/CopilotIndices/17.14.878.3237/CodeChunks.db
Binary files differ
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/CopilotIndices/17.14.878.3237/CodeChunks.db-shm
Binary files differ
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/CopilotIndices/17.14.878.3237/CodeChunks.db-wal
Binary files differ
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/CopilotIndices/17.14.878.3237/SemanticSymbols.db
Binary files differ
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/CopilotIndices/17.14.878.3237/SemanticSymbols.db-shm
Binary files differ
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/.vs/WIDESEA_WMSServer/CopilotIndices/17.14.878.3237/SemanticSymbols.db-wal
Binary files differ
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_AllocateService/AllocateService.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WIDESEA_Core.BaseRepository;
using WIDESEA_Core.BaseServices;
using WIDESEA_IAllocateService;
using WIDESEA_Model.Models;
using WIDESEA_Model.Models.Allocate;
namespace WIDESEA_AllocateService
{
    public partial class AllocateService : ServiceBase<Dt_AllocateOrder, IRepository<Dt_AllocateOrder>>, IAllocateService
    {
        public AllocateService(IRepository<Dt_AllocateOrder> BaseDal) : base(BaseDal)
        {
        }
        public IRepository<Dt_AllocateOrder> Repository => BaseDal;
    }
}
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_AllocateService/WIDESEA_AllocateService.csproj
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>
  <ItemGroup>
    <ProjectReference Include="..\WIDESEA_Core\WIDESEA_Core.csproj" />
    <ProjectReference Include="..\WIDESEA_IAllocateService\WIDESEA_IAllocateService.csproj" />
    <ProjectReference Include="..\WIDESEA_Model\WIDESEA_Model.csproj" />
  </ItemGroup>
</Project>
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_BasicService/DailySequenceService.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,245 @@
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Logging;
using OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;
using SqlSugar;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WIDESEA_Core.BaseRepository;
using WIDESEA_Core.BaseServices;
using WIDESEA_IBasicService;
using WIDESEA_Model.Models;
using WIDESEA_Model.Models.Basic;
namespace WIDESEA_BasicService
{
    public class DailySequenceService : ServiceBase<DT_DailySequence, IRepository<DT_DailySequence>>, IDailySequenceService
    {
        private readonly ILogger<DailySequenceService> _logger;
        private readonly IMemoryCache _cache;
        private readonly SemaphoreSlim _lock = new(1, 1);
        private readonly IUnitOfWorkManage _unitOfWorkManage;
        public DailySequenceService(IRepository<DT_DailySequence> BaseDal, ILogger<DailySequenceService> logger, IMemoryCache cache, IUnitOfWorkManage unitOfWorkManage) : base(BaseDal)
        {
            _logger = logger;
            _cache = cache;
            _unitOfWorkManage = unitOfWorkManage;
        }
        public IRepository<DT_DailySequence> Repository => BaseDal;
        public async Task<int> GetNextSequenceAsync()
        {
            return await GetNextSequenceAsync("MESBarcode");
        }
        public async Task<int> GetNextSequence2Async(string sequenceKey)
        {
            var today = DateTime.Today;
            var cacheKey = $"DailySequence_{sequenceKey}_{today:yyyyMMdd}";
            await _lock.WaitAsync();
            try
            {
                // å…ˆæ£€æŸ¥ç¼“å­˜
                if (_cache.TryGetValue(cacheKey, out int currentValue))
                {
                    currentValue++;
                    _cache.Set(cacheKey, currentValue, TimeSpan.FromHours(24));
                    return currentValue;
                }
                // ç¼“存中没有,从数据库获取或创建
                var result= await Repository.Db.Ado.UseTranAsync(async () =>
                {
                    // æ¸…理昨天的记录
                    var yesterday = today.AddDays(-1);
                    await Repository.Db.Deleteable<DT_DailySequence>()
                        .Where(x => x.SequenceDate == yesterday && x.SequenceKey == sequenceKey)
                        .ExecuteCommandAsync();
                    // æŸ¥æ‰¾æˆ–创建今天的记录
                    var sequence = await Repository.Db.Queryable<DT_DailySequence>()
                        .Where(x => x.SequenceDate == today && x.SequenceKey == sequenceKey)
                        .With(SqlWith.UpdLock)
                        .FirstAsync();
                    int nextValue;
                    if (sequence == null)
                    {
                        sequence = new DT_DailySequence
                        {
                            SequenceDate = today,
                            SequenceKey = sequenceKey,
                            CurrentValue = 1,
                        };
                        await Repository.Db.Insertable(sequence).ExecuteReturnEntityAsync();
                        nextValue = 1;
                    }
                    else
                    {
                        nextValue = sequence.CurrentValue + 1;
                        sequence.CurrentValue = nextValue;
                        await Repository.Db.Updateable(sequence).ExecuteCommandAsync();
                    }
                    // è®¾ç½®ç¼“å­˜
                    _cache.Set(cacheKey, nextValue, TimeSpan.FromHours(24));
                    return nextValue;
                });
                return result.Data;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取序列号失败,SequenceKey: {SequenceKey}", sequenceKey);
                throw;
            }
            finally
            {
                _lock.Release();
            }
        }
        public async Task<int> GetNextSequenceAsync(string sequenceKey)
        {
            var today = DateTime.Today;
            var cacheKey = $"DailySequence_{sequenceKey}_{today:yyyyMMdd}";
            await _lock.WaitAsync();
            try
            {
                // æ£€æŸ¥ç¼“存中是否有今天的序列值
                if (!_cache.TryGetValue(cacheKey, out int currentValue))
                {
                    // ç¼“存中没有,从数据库获取或创建
                    currentValue = await GetOrCreateSequenceFromDatabase(today, sequenceKey);
                    // è®¾ç½®ç¼“存,过期时间为今天结束
                    var _cacheOptions = new MemoryCacheEntryOptions
                    {
                        AbsoluteExpiration = today.AddDays(1)
                    };
                    _cache.Set(cacheKey, currentValue, _cacheOptions);
                    return currentValue;
                }
                // ç¼“存中存在,递增并更新缓存
                currentValue++;
                var cacheOptions = new MemoryCacheEntryOptions
                {
                    AbsoluteExpiration = today.AddDays(1)
                };
                _cache.Set(cacheKey, currentValue, cacheOptions);
                // å¼‚步更新到数据库
                _ = Task.Run(async () =>
                {
                    try
                    {
                        await UpdateSequenceInDatabase(today, sequenceKey, currentValue);
                    }
                    catch (Exception ex)
                    {
                        _logger.LogWarning(ex, "异步更新序列到数据库失败,SequenceKey: {SequenceKey}", sequenceKey);
                    }
                });
                return currentValue;
            }
            finally
            {
                _lock.Release();
            }
        }
        private async Task<int> GetOrCreateSequenceFromDatabase(DateTime date, string sequenceKey)
        {
            var result= await Repository.Db.Ado.UseTranAsync(async () =>
            {
                var sequence = await Repository.Db.Queryable<DT_DailySequence>()
                    .Where(x => x.SequenceDate == date && x.SequenceKey == sequenceKey)
                    .With(SqlWith.UpdLock)
                    .FirstAsync();
                if (sequence == null)
                {
                    sequence = new DT_DailySequence
                    {
                        SequenceDate = date,
                        SequenceKey = sequenceKey,
                        CurrentValue = 1,
                    };
                    await Repository.Db.Insertable(sequence).ExecuteReturnEntityAsync();
                    return 1;
                }
                else
                {
                    var nextValue = sequence.CurrentValue + 1;
                    sequence.CurrentValue = nextValue;
                    await Repository.Db.Updateable(sequence).ExecuteCommandAsync();
                    return nextValue;
                }
            }) ;
             return result.Data;
        }
        private async Task UpdateSequenceInDatabase(DateTime date, string sequenceKey, int value)
        {
            var sequence = await Repository.Db.Queryable<DT_DailySequence>()
                .Where(x => x.SequenceDate == date && x.SequenceKey == sequenceKey)
                .FirstAsync();
            if (sequence != null)
            {
                sequence.CurrentValue = value;
                await Repository.Db.Updateable(sequence).ExecuteCommandAsync();
            }
            else
            {
                // å¦‚果数据库记录不存在,则创建
                sequence = new DT_DailySequence
                {
                    SequenceDate = date,
                    SequenceKey = sequenceKey,
                    CurrentValue = value,
                };
                await Repository.Db.Insertable(sequence).ExecuteCommandAsync();
            }
        }
        public async Task CleanOldSequencesAsync(int keepDays = 30)
        {
            try
            {
                var deleteBefore = DateTime.Today.AddDays(-keepDays);
                var deletedCount = await Repository.Db.Deleteable<DT_DailySequence>()
                    .Where(x => x.SequenceDate < deleteBefore)
                    .ExecuteCommandAsync();
                for (int i = 1; i < keepDays; i++) {
                    var cacheKey = $"DailySequence_MESBarcode_{DateTime.Now.AddDays(-i):yyyyMMdd}";
                    _cache.Remove(cacheKey);
                }
                _logger.LogInformation("清理了 {Count} æ¡ {Days} å¤©å‰çš„序列记录", deletedCount, keepDays);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "清理旧序列记录失败");
                throw;
            }
        }
    }
}
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_BasicService/ESSApiService.cs
@@ -6,6 +6,7 @@
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using WIDESEA_DTO.Basic;
using WIDESEA_IBasicService;
@@ -27,10 +28,17 @@
        /// </summary>
        public async Task MoveContainerAsync(MoveContainerRequest request)
        {
            var url = "conveyor/moveContainer";
            try
            {
                var url = "conveyor/moveContainer";
            var result = await PostAsync<MoveContainerRequest, ApiResponse<string>>(url, request);
                var result = await PostAsync<MoveContainerRequest, ApiResponse<string>>(url, request);
            }
            catch (Exception ex)
            {
                _logger.LogInformation("容器流动失败:  " + ex.Message);
            }
        }
        /// <summary>
@@ -40,21 +48,30 @@
        /// <returns></returns>
        public async Task<bool> CreateTaskAsync(TaskModel request)
        {
            _logger.LogInformation("创建任务Request:  " +  JsonConvert.SerializeObject(request));
            var url = "task/create";
            var result = await PostAsync<TaskModel, ApiResponse<TasksData>>(url, request);
            if (result != null && result.Code == 0)
            try
            {
                return true;
                _logger.LogInformation("创建任务Request:  " + JsonConvert.SerializeObject(request));
                var url = "task/create";
                var result = await PostAsync<TaskModel, ApiResponse<TasksData>>(url, request);
                if (result != null && result.Code == 0)
                {
                    return true;
                }
                return false;
            }
            return false;
            catch (Exception ex)
            {
                _logger.LogInformation("创建任务失败:  " + ex.Message);
                return false;
            }
        }
        private async Task<TResponse> PostAsync<TRequest, TResponse>(string url, TRequest request)
        {
            string json = JsonConvert.SerializeObject(request, new JsonSerializerSettings
            {
                ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver()
@@ -67,13 +84,14 @@
            using var response = await _client.PostAsync(url, content);
            string body = await response.Content.ReadAsStringAsync();
            _logger.LogInformation($"ESSAPI post :  {_client.BaseAddress}  {url}   {body}" );
            _logger.LogInformation($"ESSAPI post :  {_client.BaseAddress}  {url}   {body}");
            if (!response.IsSuccessStatusCode)
            {
                throw new HttpRequestException(body);
            }
            return JsonConvert.DeserializeObject<TResponse>(body);
        }
    }
}
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_BasicService/ErpApiService.cs
@@ -1,4 +1,5 @@
using NetTaste;
using Microsoft.Extensions.Logging;
using NetTaste;
using Newtonsoft.Json;
using Org.BouncyCastle.Ocsp;
using SqlSugar.Extensions;
@@ -21,13 +22,15 @@
        private readonly ISupplierInfoService _supplierInfoService;
        private readonly IMaterialUnitService _materialUnitService;
        private readonly IMaterielInfoService _materielInfoService;
        private readonly ILogger<ErpApiService> _logger;
        public ErpApiService(IHttpClientFactory httpClientFactory, ISupplierInfoService supplierInfoService, IMaterialUnitService materialUnitService, IMaterielInfoService materielInfoService)
        public ErpApiService(IHttpClientFactory httpClientFactory, ISupplierInfoService supplierInfoService, IMaterialUnitService materialUnitService, IMaterielInfoService materielInfoService, ILogger<ErpApiService> logger)
        {
            _httpClientFactory = httpClientFactory;
            _supplierInfoService = supplierInfoService;
            _materialUnitService = materialUnitService;
            _materielInfoService = materielInfoService;
            _logger = logger;
        }
        /// <summary>
@@ -36,10 +39,19 @@
        /// <returns></returns>
        public async Task<string> GetTokenAsync()
        {
            var request = new TokenRequest { appId = "BG_SYSTEM", secretKey = "7e9239c1e132462a9cf03bfa342a044aMTcxODE5MzgxODI4Mw" };
            var response = await PostAsync<TokenRequest, TokenResponse>("auth/getAccessToken", request, includeToken: false);
            var _token = response?.data?.access_token;
            return _token ?? "";
            try
            {
                var request = new TokenRequest { appId = "BG_SYSTEM", secretKey = "7e9239c1e132462a9cf03bfa342a044aMTcxODE5MzgxODI4Mw" };
                var response = await PostAsync<TokenRequest, TokenResponse>("auth/getAccessToken", request, includeToken: false);
                var _token = response?.data?.access_token;
                return _token ?? "";
            }
            catch (Exception ex)
            {
                _logger.LogInformation("ErpApiService GetTokenAsync失败:  " + ex.Message);
                return "";
            }
        }
@@ -50,49 +62,57 @@
        /// <returns></returns>
        public async Task GetSuppliersAsync(string vendorCode = null)
        {
            var req = new SupplierRequest { vendorCode = vendorCode };
            var result = await PostAsync<SupplierRequest, SupplierResponse>("erp/getVendorInfo", req, includeToken: true);
            if (result != null && result.data != null && result.data.Any())
            try
            {
                var dblists = _supplierInfoService.Repository.QueryData();
                var excepts = dblists.Select(O => O.SupplierCode).Except(result.data.Select(o => o.vendorCode));
                foreach (var except in excepts)
                var req = new SupplierRequest { vendorCode = vendorCode };
                var result = await PostAsync<SupplierRequest, SupplierResponse>("erp/getVendorInfo", req, includeToken: true);
                if (result != null && result.data != null && result.data.Any())
                {
                    var first = dblists.FirstOrDefault(o => o.SupplierCode == except);
                    if (first != null)
                    var dblists = _supplierInfoService.Repository.QueryData();
                    var excepts = dblists.Select(O => O.SupplierCode).Except(result.data.Select(o => o.vendorCode));
                    foreach (var except in excepts)
                    {
                        _supplierInfoService.Repository.DeleteData(first);
                    }
                }
                foreach (var item in result.data)
                {
                    var first = dblists.FirstOrDefault(o => o.SupplierCode == item.vendorCode);
                    if (first != null)
                    {
                        first.SupplierCode = item.vendorCode;
                        first.SupplierName = item.vendorName;
                        first.SupplierShortName = item.vendorShortName;
                        first.Status = item.effective.ObjToInt();
                        first.CreateDate = item.createDate.ObjToDate();
                        first.ModifyDate = item.modifyDate.ObjToDate();
                        _supplierInfoService.Repository.UpdateData(first);
                    }
                    else
                    {
                        Dt_SupplierInfo dt_SupplierInfo = new()
                        var first = dblists.FirstOrDefault(o => o.SupplierCode == except);
                        if (first != null)
                        {
                            SupplierCode = item.vendorCode,
                            SupplierName = item.vendorName,
                            SupplierShortName = item.vendorShortName,
                            Status = item.effective.ObjToInt(),
                            CreateDate = item.createDate.ObjToDate(),
                            Creater = "ERP",
                            Modifier = "ERP",
                            ModifyDate = item.modifyDate.ObjToDate()
                        };
                        _supplierInfoService.Repository.AddData(dt_SupplierInfo);
                            _supplierInfoService.Repository.DeleteData(first);
                        }
                    }
                    foreach (var item in result.data)
                    {
                        var first = dblists.FirstOrDefault(o => o.SupplierCode == item.vendorCode);
                        if (first != null)
                        {
                            first.SupplierCode = item.vendorCode;
                            first.SupplierName = item.vendorName;
                            first.SupplierShortName = item.vendorShortName;
                            first.Status = item.effective.ObjToInt();
                            first.CreateDate = item.createDate.ObjToDate();
                            first.ModifyDate = item.modifyDate.ObjToDate();
                            _supplierInfoService.Repository.UpdateData(first);
                        }
                        else
                        {
                            Dt_SupplierInfo dt_SupplierInfo = new()
                            {
                                SupplierCode = item.vendorCode,
                                SupplierName = item.vendorName,
                                SupplierShortName = item.vendorShortName,
                                Status = item.effective.ObjToInt(),
                                CreateDate = item.createDate.ObjToDate(),
                                Creater = "ERP",
                                Modifier = "ERP",
                                ModifyDate = item.modifyDate.ObjToDate()
                            };
                            _supplierInfoService.Repository.AddData(dt_SupplierInfo);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                _logger.LogInformation("ErpApiService GetSuppliersAsync失败:  " + ex.Message);
            }
        }
@@ -104,160 +124,175 @@
        /// <returns></returns>
        public async Task GetMaterialUnitAsync(string itemNo = null)
        {
            var req = new MaterialUnitRequest { itemNo = itemNo };
            var result = await PostAsync<MaterialUnitRequest, MaterialUnitResponse>("erp/getMaterialUnit", req, true);
            if (result != null && result.data != null && result.data.Any())
            try
            {
                var dblists = _materialUnitService.Repository.QueryData();
                var excepts = dblists.Select(O => O.ItemNo).Except(result.data.Select(o => o.itemNo));
                foreach (var except in excepts)
                var req = new MaterialUnitRequest { itemNo = itemNo };
                var result = await PostAsync<MaterialUnitRequest, MaterialUnitResponse>("erp/getMaterialUnit", req, true);
                if (result != null && result.data != null && result.data.Any())
                {
                    var first = dblists.FirstOrDefault(o => o.ItemNo == except);
                    if (first != null)
                    var dblists = _materialUnitService.Repository.QueryData();
                    var excepts = dblists.Select(O => O.ItemNo).Except(result.data.Select(o => o.itemNo));
                    foreach (var except in excepts)
                    {
                        _materialUnitService.Repository.DeleteData(first);
                    }
                }
                foreach (var item in result.data)
                {
                    var first = dblists.FirstOrDefault(o => o.ItemNo == item.itemNo);
                    if (first != null)
                    {
                        first.ItemNo = item.itemNo;
                        first.ProductName = item.productName;
                        first.FromUom = item.fromUom;
                        first.ToUom = item.toUom;
                        first.Ratio = item.ratio.ObjToDecimal();
                        first.Creater = "ERP";
                        first.Modifier = "ERP";
                        first.CreateDate = item.createDate.ObjToDate();
                        first.ModifyDate = item.modifyDate.ObjToDate();
                        _materialUnitService.Repository.UpdateData(first);
                    }
                    else
                    {
                        Dt_MaterialUnit dt_MaterialUnit = new()
                        var first = dblists.FirstOrDefault(o => o.ItemNo == except);
                        if (first != null)
                        {
                            ItemNo = item.itemNo,
                            ProductName = item.productName,
                            FromUom = item.fromUom,
                            ToUom = item.toUom,
                            Ratio = item.ratio.ObjToDecimal(),
                            CreateDate = item.createDate.ObjToDate(),
                            Creater = "ERP",
                            Modifier = "ERP",
                            ModifyDate = item.modifyDate.ObjToDate()
                        };
                        _materialUnitService.Repository.AddData(dt_MaterialUnit);
                            _materialUnitService.Repository.DeleteData(first);
                        }
                    }
                    foreach (var item in result.data)
                    {
                        var first = dblists.FirstOrDefault(o => o.ItemNo == item.itemNo);
                        if (first != null)
                        {
                            first.ItemNo = item.itemNo;
                            first.ProductName = item.productName;
                            first.FromUom = item.fromUom;
                            first.ToUom = item.toUom;
                            first.Ratio = item.ratio.ObjToDecimal();
                            first.Creater = "ERP";
                            first.Modifier = "ERP";
                            first.CreateDate = item.createDate.ObjToDate();
                            first.ModifyDate = item.modifyDate.ObjToDate();
                            _materialUnitService.Repository.UpdateData(first);
                        }
                        else
                        {
                            Dt_MaterialUnit dt_MaterialUnit = new()
                            {
                                ItemNo = item.itemNo,
                                ProductName = item.productName,
                                FromUom = item.fromUom,
                                ToUom = item.toUom,
                                Ratio = item.ratio.ObjToDecimal(),
                                CreateDate = item.createDate.ObjToDate(),
                                Creater = "ERP",
                                Modifier = "ERP",
                                ModifyDate = item.modifyDate.ObjToDate()
                            };
                            _materialUnitService.Repository.AddData(dt_MaterialUnit);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                _logger.LogInformation("ErpApiService GetMaterialUnitAsync å¤±è´¥:  " + ex.Message);
            }
        }
        public async Task GetMaterialInfoAsync(MaterialRequest materialRequest)
        {
            var first = WIDESEA_Core.Helper.AppSettings.GetValue("FirstMaterialSync").ObjToBool();
            if (first)
            try
            {
                var _token = await GetTokenAsync();
                for (int i = 1; i < 400; i++)
                var first = WIDESEA_Core.Helper.AppSettings.GetValue("FirstMaterialSync").ObjToBool();
                if (first)
                {
                    materialRequest.pageNum = i;
                    var _token = await GetTokenAsync();
                    for (int i = 1; i < 400; i++)
                    {
                        materialRequest.pageNum = i;
                        materialRequest.pageSize = 5000;
                        var result = await PostAsync<MaterialRequest, MaterialResponse>("erp/getMaterialInfo", materialRequest, _token, true);
                        if (result != null && result.data != null && result.data.Any())
                        {
                            foreach (var item in result.data)
                            {
                                Dt_MaterielInfo dt_MaterielInfo = new Dt_MaterielInfo()
                                {
                                    MaterielModel = item.productModel,
                                    MaterielCode = item.itemNo,
                                    MaterielName = item.productName,
                                    MaterielSpec = item.spec,
                                    productTypeDesc = item.productTypeDesc,
                                    productFamilyName = item.productFamilyName,
                                    productFamilyShortName = item.productFamilyShortName,
                                    plcode = item.plcode,
                                    pl = item.pl,
                                    drawingNo = item.drawingNo,
                                    mversion = item.mversion,
                                    warehouseName = item.warehouseName,
                                    usageUOM = item.usageUOM,
                                    purchaseUOM = item.purchaseUOM,
                                    inventoryUOM = item.inventoryUOM,
                                    CreateDate = item.createDate.ObjToDate(),
                                    ModifyDate = item.modifyDate.ObjToDate(),
                                };
                                _materielInfoService.Repository.AddData(dt_MaterielInfo);
                            }
                        }
                    }
                }
                else
                {
                    materialRequest.modifyDateStart = DateTime.Now.AddDays(-1).Date.ToString("yyyy-MM-dd") + " 00:00:01";
                    materialRequest.modifyDateEnd = DateTime.Now.ToString("yyyy-MM-dd HH:mm") + ":01";
                    materialRequest.pageNum = 1;
                    materialRequest.pageSize = 5000;
                    var result = await PostAsync<MaterialRequest, MaterialResponse>("erp/getMaterialInfo", materialRequest, _token, true);
                    var result = await PostAsync<MaterialRequest, MaterialResponse>("erp/getMaterialInfo", materialRequest, true, true);
                    if (result != null && result.data != null && result.data.Any())
                    {
                        foreach (var item in result.data)
                        {
                            Dt_MaterielInfo dt_MaterielInfo = new Dt_MaterielInfo()
                            var dbfirst = _materielInfoService.Repository.QueryData(x => x.MaterielModel == item.productModel && x.MaterielCode == item.itemNo).FirstOrDefault();
                            if (dbfirst != null)
                            {
                                MaterielModel = item.productModel,
                                MaterielCode = item.itemNo,
                                MaterielName = item.productName,
                                MaterielSpec = item.spec,
                                productTypeDesc = item.productTypeDesc,
                                productFamilyName = item.productFamilyName,
                                productFamilyShortName = item.productFamilyShortName,
                                plcode = item.plcode,
                                pl = item.pl,
                                drawingNo = item.drawingNo,
                                mversion = item.mversion,
                                warehouseName = item.warehouseName,
                                usageUOM = item.usageUOM,
                                purchaseUOM = item.purchaseUOM,
                                inventoryUOM = item.inventoryUOM,
                                CreateDate = item.createDate.ObjToDate(),
                                ModifyDate = item.modifyDate.ObjToDate(),
                            };
                            _materielInfoService.Repository.AddData(dt_MaterielInfo);
                                dbfirst.MaterielModel = item.productModel;
                                dbfirst.MaterielCode = item.itemNo;
                                dbfirst.MaterielName = item.productName;
                                dbfirst.MaterielSpec = item.spec;
                                dbfirst.productTypeDesc = item.productTypeDesc;
                                dbfirst.productFamilyName = item.productFamilyName;
                                dbfirst.productFamilyShortName = item.productFamilyShortName;
                                dbfirst.plcode = item.plcode;
                                dbfirst.pl = item.pl;
                                dbfirst.drawingNo = item.drawingNo;
                                dbfirst.mversion = item.mversion;
                                dbfirst.warehouseName = item.warehouseName;
                                dbfirst.usageUOM = item.usageUOM;
                                dbfirst.purchaseUOM = item.purchaseUOM;
                                dbfirst.inventoryUOM = item.inventoryUOM;
                                dbfirst.CreateDate = item.createDate.ObjToDate();
                                dbfirst.ModifyDate = item.modifyDate.ObjToDate();
                                _materielInfoService.Repository.UpdateData(dbfirst);
                            }
                            else
                            {
                                Dt_MaterielInfo dt_MaterielInfo = new Dt_MaterielInfo()
                                {
                                    MaterielModel = item.productModel,
                                    MaterielCode = item.itemNo,
                                    MaterielName = item.productName,
                                    MaterielSpec = item.spec,
                                    productTypeDesc = item.productTypeDesc,
                                    productFamilyName = item.productFamilyName,
                                    productFamilyShortName = item.productFamilyShortName,
                                    plcode = item.plcode,
                                    pl = item.pl,
                                    drawingNo = item.drawingNo,
                                    mversion = item.mversion,
                                    warehouseName = item.warehouseName,
                                    usageUOM = item.usageUOM,
                                    purchaseUOM = item.purchaseUOM,
                                    inventoryUOM = item.inventoryUOM,
                                    CreateDate = item.createDate.ObjToDate(),
                                    ModifyDate = item.modifyDate.ObjToDate(),
                                };
                                _materielInfoService.Repository.AddData(dt_MaterielInfo);
                            }
                        }
                    }
                }
            }
            else
            catch (Exception ex)
            {
                materialRequest.modifyDateStart = DateTime.Now.AddDays(-1).Date.ToString("yyyy-MM-dd") + " 00:00:01";
                materialRequest.modifyDateEnd = DateTime.Now.ToString("yyyy-MM-dd HH:mm")+ ":01";
                materialRequest.pageNum = 1;
                materialRequest.pageSize = 5000;
                _logger.LogInformation("ErpApiService GetMaterialInfoAsync å¤±è´¥:  " + ex.Message);
                var result = await PostAsync<MaterialRequest, MaterialResponse>("erp/getMaterialInfo", materialRequest, true, true);
                if (result != null && result.data != null && result.data.Any())
                {
                    foreach (var item in result.data)
                    {
                        var dbfirst = _materielInfoService.Repository.QueryData(x => x.MaterielModel == item.productModel && x.MaterielCode == item.itemNo).FirstOrDefault();
                        if (dbfirst != null)
                        {
                            dbfirst.MaterielModel = item.productModel;
                            dbfirst.MaterielCode = item.itemNo;
                            dbfirst.MaterielName = item.productName;
                            dbfirst.MaterielSpec = item.spec;
                            dbfirst.productTypeDesc = item.productTypeDesc;
                            dbfirst.productFamilyName = item.productFamilyName;
                            dbfirst.productFamilyShortName = item.productFamilyShortName;
                            dbfirst.plcode = item.plcode;
                            dbfirst.pl = item.pl;
                            dbfirst.drawingNo = item.drawingNo;
                            dbfirst.mversion = item.mversion;
                            dbfirst.warehouseName = item.warehouseName;
                            dbfirst.usageUOM = item.usageUOM;
                            dbfirst.purchaseUOM = item.purchaseUOM;
                            dbfirst.inventoryUOM = item.inventoryUOM;
                            dbfirst.CreateDate = item.createDate.ObjToDate();
                            dbfirst.ModifyDate = item.modifyDate.ObjToDate();
                            _materielInfoService.Repository.UpdateData(dbfirst);
                        }
                        else
                        {
                            Dt_MaterielInfo dt_MaterielInfo = new Dt_MaterielInfo()
                            {
                                MaterielModel = item.productModel,
                                MaterielCode = item.itemNo,
                                MaterielName = item.productName,
                                MaterielSpec = item.spec,
                                productTypeDesc = item.productTypeDesc,
                                productFamilyName = item.productFamilyName,
                                productFamilyShortName = item.productFamilyShortName,
                                plcode = item.plcode,
                                pl = item.pl,
                                drawingNo = item.drawingNo,
                                mversion = item.mversion,
                                warehouseName = item.warehouseName,
                                usageUOM = item.usageUOM,
                                purchaseUOM = item.purchaseUOM,
                                inventoryUOM = item.inventoryUOM,
                                CreateDate = item.createDate.ObjToDate(),
                                ModifyDate = item.modifyDate.ObjToDate(),
                            };
                            _materielInfoService.Repository.AddData(dt_MaterielInfo);
                        }
                    }
                }
            }
        }
        private async Task<TResponse> PostAsync<TRequest, TResponse>(string url, TRequest request, string _token, bool isNullSerialize = false)
@@ -314,7 +349,7 @@
            }
            else
            {
                json = JsonConvert.SerializeObject(request );
                json = JsonConvert.SerializeObject(request);
            }
            var content = new StringContent(json, Encoding.UTF8, "application/json");
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_BasicService/InvokeMESService.cs
@@ -1,4 +1,5 @@
using Newtonsoft.Json;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Org.BouncyCastle.Asn1.Ocsp;
using System;
using System.Collections.Generic;
@@ -18,12 +19,13 @@
    public class InvokeMESService : IInvokeMESService
    {
        private readonly IHttpClientFactory _httpClientFactory;
        private readonly ILogger<InvokeMESService> _logger;
        private string UserName = "12312";
        private string Password = "1";
        public InvokeMESService(IHttpClientFactory httpClientFactory)
        public InvokeMESService(IHttpClientFactory httpClientFactory, ILogger<InvokeMESService> logger)
        {
            _httpClientFactory = httpClientFactory;
            _logger = logger;
        }
        public async Task FeedbackInbound(string url, FeedbackInboundRequestModel model)
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_BasicService/LocationInfoService.cs
@@ -281,8 +281,8 @@
                                Depth = depth,
                            };
                          
   locationInfo.LocationCode = $"HAI-{locationInfo.Row.ToString().PadLeft(3, '0')}-{locationInfo.Column.ToString().PadLeft(3, '0')}-{locationInfo.Layer.ToString().PadLeft(2, '0')} ";
    locationInfo.LocationName = $"HAI{locationInfo.RoadwayNo}巷道{locationInfo.Row.ToString().PadLeft(3, '0')}行{locationInfo.Column.ToString().PadLeft(3, '0')}列{locationInfo.Layer.ToString().PadLeft(3, '0')}层 ";
   locationInfo.LocationCode = $"HAI-{locationInfo.Row.ToString().PadLeft(3, '0')}-{locationInfo.Column.ToString().PadLeft(3, '0')}-{locationInfo.Layer.ToString().PadLeft(2, '0')}";
    locationInfo.LocationName = $"HAI{locationInfo.RoadwayNo}巷道{locationInfo.Row.ToString().PadLeft(3, '0')}行{locationInfo.Column.ToString().PadLeft(3, '0')}列{locationInfo.Layer.ToString().PadLeft(3, '0')}层";
                            //locationInfo.LocationCode = $"{locationInfo.RoadwayNo}-{locationInfo.Row.ToString().PadLeft(3, '0')}-{locationInfo.Column.ToString().PadLeft(3, '0')}-{locationInfo.Layer.ToString().PadLeft(3, '0')}-{locationInfo.Depth.ToString().PadLeft(2, '0')}";
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_BasicService/MaterialUnitService.cs
@@ -1,4 +1,5 @@
using System;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@@ -13,12 +14,173 @@
{
    public class MaterialUnitService : ServiceBase<Dt_MaterialUnit, IRepository<Dt_MaterialUnit>>, IMaterialUnitService
    {
        private readonly ILogger<MaterialUnitService> _logger;
        public IRepository<Dt_MaterialUnit> Repository => BaseDal;
        public MaterialUnitService(IRepository<Dt_MaterialUnit> BaseDal) : base(BaseDal)
        public IRepository<Dt_MaterielInfo> _materielInfoRepository;
        public MaterialUnitService(IRepository<Dt_MaterialUnit> BaseDal, ILogger<MaterialUnitService> logger, IRepository<Dt_MaterielInfo> materielInfoRepository) : base(BaseDal)
        {
            _logger = logger;
            _materielInfoRepository = materielInfoRepository;
        }
        /// <summary>
        /// å•位转换
        /// </summary>
        public async Task<decimal> ConvertAsync(string materialCode, decimal quantity, string fromUnit, string toUnit)
        {
            if (string.IsNullOrEmpty(materialCode))
                throw new ArgumentException("物料编号不能为空");
            if (string.IsNullOrEmpty(fromUnit) || string.IsNullOrEmpty(toUnit))
                throw new ArgumentException("单位不能为空");
            // å¦‚果单位相同,直接返回
            if (fromUnit.Equals(toUnit, StringComparison.OrdinalIgnoreCase))
                return quantity;
            var ratio = await GetConversionRatioAsync(materialCode, fromUnit, toUnit);
            if (ratio == null)
            {
                _logger.LogWarning($"未找到物料 {materialCode} ä»Ž {fromUnit} åˆ° {toUnit} çš„单位转换关系");
                throw new InvalidOperationException($"未找到物料 {materialCode} ä»Ž {fromUnit} åˆ° {toUnit} çš„单位转换关系");
            }
            return quantity * ratio.Value;
        }
        /// <summary>
        /// é‡‡è´­å•位转库存单位
        /// </summary>
        public async Task<decimal> ConvertPurchaseToStockAsync(string materialCode, decimal quantity)
        {
            // èŽ·å–ç‰©æ–™ä¿¡æ¯
            var material = await _materielInfoRepository.Db.Queryable<Dt_MaterielInfo>()
                .Where(x => x.MaterielCode == materialCode)
                .FirstAsync();
            if (material == null)
            {
                throw new ArgumentException($"未找到物料编号: {materialCode}");
            }
            return await ConvertAsync(materialCode, quantity, material.purchaseUOM, material.inventoryUOM);
        }
        /// <summary>
        /// é¢†æ–™å•位转库存单位
        /// </summary>
        public async Task<decimal> ConvertIssueToStockAsync(string materialCode, decimal quantity)
        {
            // èŽ·å–ç‰©æ–™ä¿¡æ¯
            var material = await _materielInfoRepository.Db.Queryable<Dt_MaterielInfo>()
                .Where(x => x.MaterielCode == materialCode)
                .FirstAsync();
            if (material == null)
            {
                throw new ArgumentException($"未找到物料编号: {materialCode}");
            }
            return await ConvertAsync(materialCode, quantity, material.usageUOM, material.inventoryUOM);
        }
        /// <summary>
        /// èŽ·å–å•ä½è½¬æ¢æ¯”çŽ‡
        /// </summary>
        public async Task<decimal?> GetConversionRatioAsync(string materialCode, string fromUnit, string toUnit)
        {
            // å°è¯•直接查找转换关系
            var conversion = await Repository.Db.Queryable<Dt_MaterialUnit>()
                .Where(x => x.ItemNo == materialCode &&
                           x.FromUom == fromUnit &&
                           x.ToUom == toUnit)
                .FirstAsync();
            if (conversion != null)
            {
                return conversion.Ratio;
            }
            // å°è¯•查找反向转换关系(取倒数)
            var reverseConversion = await Repository.Db.Queryable<Dt_MaterialUnit>()
                .Where(x => x.ItemNo == materialCode &&
                           x.FromUom == toUnit &&
                           x.ToUom == fromUnit)
                .FirstAsync();
            if (reverseConversion != null)
            {
                return 1 / reverseConversion.Ratio;
            }
            // å°è¯•通过中间单位(库存单位)进行转换
            var material = await _materielInfoRepository.Db.Queryable<Dt_MaterielInfo>()
                .Where(x => x.MaterielCode == materialCode)
                .FirstAsync();
            if (material != null)
            {
                var stockUnit = material.inventoryUOM;
                // å¦‚果目标单位已经是库存单位,直接查找源单位到库存单位的转换
                if (toUnit.Equals(stockUnit, StringComparison.OrdinalIgnoreCase))
                {
                    var toStockRatio = await GetDirectRatioAsync(materialCode, fromUnit, stockUnit);
                    if (toStockRatio != null) return toStockRatio;
                }
                // å¦‚果源单位是库存单位,直接查找库存单位到目标单位的转换
                if (fromUnit.Equals(stockUnit, StringComparison.OrdinalIgnoreCase))
                {
                    var fromStockRatio = await GetDirectRatioAsync(materialCode, stockUnit, toUnit);
                    if (fromStockRatio != null) return fromStockRatio;
                }
                // é€šè¿‡åº“存单位进行间接转换:fromUnit -> stockUnit -> toUnit
                var ratio1 = await GetDirectRatioAsync(materialCode, fromUnit, stockUnit);
                var ratio2 = await GetDirectRatioAsync(materialCode, stockUnit, toUnit);
                if (ratio1 != null && ratio2 != null)
                {
                    return ratio1 * ratio2;
                }
            }
            return null;
        }
        /// <summary>
        /// èŽ·å–ç›´æŽ¥è½¬æ¢æ¯”çŽ‡ï¼ˆåŒ…å«æ­£å‘å’Œåå‘æŸ¥æ‰¾ï¼‰
        /// </summary>
        private async Task<decimal?> GetDirectRatioAsync(string materialCode, string fromUnit, string toUnit)
        {
            // æ­£å‘查找
            var conversion = await Repository.Db.Queryable<Dt_MaterialUnit>()
                .Where(x => x.ItemNo == materialCode &&
                           x.FromUom == fromUnit &&
                           x.ToUom == toUnit)
                .FirstAsync();
            if (conversion != null)
            {
                return conversion.Ratio;
            }
            // åå‘查找
            var reverseConversion = await Repository.Db.Queryable<Dt_MaterialUnit>()
                .Where(x => x.ItemNo == materialCode &&
                           x.FromUom == toUnit &&
                           x.ToUom == fromUnit)
                .FirstAsync();
            if (reverseConversion != null)
            {
                return 1 / reverseConversion.Ratio;
            }
            return null;
        }
    }
}
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_Common/LocationEnum/LocationStatusEnum.cs
@@ -23,6 +23,7 @@
        [Description("锁定")]
        Lock = 1,
        /// <summary>
        /// æœ‰è´§é”å®š
        /// </summary>
@@ -40,11 +41,10 @@
        /// </summary>
        [Description("有货")]
        InStock = 100,
        /// <summary>
        /// å¤§æ‰˜ç›˜é”å®š
        /// ç©ºæ‰˜ç›˜
        /// </summary>
        [Description("大托盘锁定")]
        PalletLock = 99
        [Description("空托盘")]
        Pallet = 99
    }
}
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_Common/OrderEnum/InboundOrderMenu.cs
@@ -90,4 +90,71 @@
        [Description("其他入库单")]
        Other = 130
    }
    /// <summary>
    /// å•据类型枚举
    /// </summary>
    public enum DocumentType
    {
        /// <summary>
        /// é‡‡è´­å…¥åº“单
        /// </summary>
        [Description("采购入库")]
        PurchaseInbound = 11,
        /// <summary>
        /// æ‚收单
        /// </summary>
        [Description("杂收单")]
        MiscellaneousReceipt = 12,
        /// <summary>
        /// ç”Ÿäº§é€€æ–™å•
        /// </summary>
        [Description("生产退料单")]
        ProductionReturn = 13,
        /// <summary>
        /// å¤–协退料单
        /// </summary>
        [Description("外协退料单")]
        OutsourcingReturn = 14,
        /// <summary>
        /// é”€å”®é€€åº“单
        /// </summary>
        [Description("销售退库单")]
        SalesReturn = 15,
        /// <summary>
        /// å·¥å•领料单
        /// </summary>
        [Description("工单领料出库单")]
        WorkOrderPicking = 21,
        /// <summary>
        /// æ‚发单
        /// </summary>
        [Description("杂发单")]
        MiscellaneousIssue = 22,
        /// <summary>
        /// é€€è´§å•
        /// </summary>
        [Description("退货单")]
        ReturnGoods = 23,
        /// <summary>
        /// é”€å”®å‡ºåº“单
        /// </summary>
        [Description("销售出库单")]
        SalesOutbound = 24,
        /// <summary>
        /// å¤–协领料申请单
        /// </summary>
        [Description("外协领料申请单")]
        OutsourcingPickingRequest = 25
    }
}
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_Common/TaskEnum/TaskTypeEnum.cs
@@ -7,6 +7,41 @@
namespace WIDESEA_Common.TaskEnum
{
    /// <summary>
    /// ä»»åŠ¡ç±»åž‹
    /// </summary>
    public enum TaskType
    {
        /// <summary>
        /// ç»„盘
        /// </summary>
        [Description("组盘")]
        SetPlate = 0,
        /// <summary>
        /// å…¥åº“
        /// </summary>
        [Description("入库")]
        EnterDepot = 1,
        /// <summary>
        /// å‡ºåº“
        /// </summary>
        [Description("出库")]
        OutDepot = 2,
        /// <summary>
        /// ç§»åº“
        /// </summary>
        [Description("移库")]
        TransferDepot = 3,
        /// <summary>
        ///  æ¬è¿
        /// </summary>
        [Description("搬运")]
        Delivery = 5,
    }
    public enum TaskTypeEnum
    {
        /// <summary>
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_DTO/Allocate/AllocateDto.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,139 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WIDESEA_DTO.Allocate
{
    /// <summary>
    ///
    /// </summary>
    [JsonObject(MemberSerialization.OptIn)]
    public class AllocateDto
    {
        /// <summary>
        /// è¯·æ±‚编码
        /// </summary>
        [JsonProperty("reqCode")]
        public string ReqCode { get; set; }
        /// <summary>
        /// è¯·æ±‚æ—¶é—´
        /// </summary>
        [JsonProperty("reqTime")]
        public DateTime ReqTime { get; set; }
        /// <summary>
        /// è®¢å•编号
        /// </summary>
        [JsonProperty("orderNo")]
        public string OrderNo { get; set; }
        /// <summary>
        /// ä¸šåŠ¡ç±»åž‹
        /// </summary>
        [JsonProperty("business_type")]
        public string BusinessType { get; set; }
        /// <summary>
        /// æ˜¯å¦åˆ†æ‰¹
        /// </summary>
        [JsonProperty("isBatch")]
        public bool IsBatch { get; set; }
        /// <summary>
        /// åŽ‚åŒºä»£ç 
        /// </summary>
        [JsonProperty("factoryArea")]
        public string FactoryArea { get; set; }
        /// <summary>
        /// æ“ä½œç±»åž‹
        /// </summary>
        [JsonProperty("operationType")]
        public int OperationType { get; set; }
        /// <summary>
        /// è®¢å•详情列表
        /// </summary>
        [JsonProperty("details")]
        public List<AllocateDtoDetail> Details { get; set; }
    }
    /// <summary>
    /// è®¢å•详情
    /// </summary>
    [JsonObject(MemberSerialization.OptIn)]
    public class AllocateDtoDetail
    {
        /// <summary>
        /// ä»“库编码
        /// </summary>
        [JsonProperty("warehouseCode")]
        public string WarehouseCode { get; set; }
        /// <summary>
        /// ç‰©æ–™ç¼–码
        /// </summary>
        [JsonProperty("materialCode")]
        public string MaterialCode { get; set; }
        /// <summary>
        /// è¡Œå·
        /// </summary>
        [JsonProperty("lineNo")]
        public string LineNo { get; set; }
        /// <summary>
        /// æ•°é‡
        /// </summary>
        [JsonProperty("qty")]
        public decimal Qty { get; set; }
        /// <summary>
        /// å•位
        /// </summary>
        [JsonProperty("unit")]
        public string Unit { get; set; }
        /// <summary>
        /// æ¡ç åˆ—表
        /// </summary>
        [JsonProperty("barcodes")]
        public List<BarcodeInfo>? Barcodes { get; set; }
    }
    /// <summary>
    /// æ¡ç ä¿¡æ¯
    /// </summary>
    [JsonObject(MemberSerialization.OptIn)]
    public class BarcodeInfo
    {
        /// <summary>
        /// æ¡ç 
        /// </summary>
        [JsonProperty("barcode")]
        public string Barcode { get; set; }
        /// <summary>
        /// æ‰¹æ¬¡å·
        /// </summary>
        [JsonProperty("batchNo")]
        public string BatchNo { get; set; }
        /// <summary>
        /// æ•°é‡
        /// </summary>
        [JsonProperty("qty")]
        public decimal Qty { get; set; }
        /// <summary>
        /// å•位
        /// </summary>
        [JsonProperty("unit")]
        public string Unit { get; set; }
    }
}
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_IAllocateService/IAllocateService.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WIDESEA_Core.BaseRepository;
using WIDESEA_Core.BaseServices;
using WIDESEA_Model.Models;
using WIDESEA_Model.Models.Allocate;
namespace WIDESEA_IAllocateService
{
    public interface IAllocateService : IService<Dt_AllocateOrder>
    {
        IRepository<Dt_AllocateOrder> Repository { get; }
    }
}
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_IAllocateService/WIDESEA_IAllocateService.csproj
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>
  <ItemGroup>
    <ProjectReference Include="..\WIDESEA_Core\WIDESEA_Core.csproj" />
    <ProjectReference Include="..\WIDESEA_Model\WIDESEA_Model.csproj" />
  </ItemGroup>
</Project>
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_IBasicService/IDailySequenceService.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WIDESEA_Core.BaseRepository;
using WIDESEA_Core.BaseServices;
using WIDESEA_Model.Models;
using WIDESEA_Model.Models.Basic;
namespace WIDESEA_IBasicService
{
    public interface IDailySequenceService : IService<DT_DailySequence>
    {
        IRepository<DT_DailySequence> Repository { get; }
        Task<int> GetNextSequenceAsync();
    }
}
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_IBasicService/IMaterialUnitService.cs
@@ -13,5 +13,11 @@
    public interface IMaterialUnitService : IService<Dt_MaterialUnit>
    {
        IRepository<Dt_MaterialUnit> Repository { get; }
          Task<decimal> ConvertAsync(string materialCode, decimal quantity, string fromUnit, string toUnit);
        Task<decimal> ConvertPurchaseToStockAsync(string materialCode, decimal quantity);
        Task<decimal> ConvertIssueToStockAsync(string materialCode, decimal quantity);
    }
}
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_ITaskInfoService/ITaskService.cs
@@ -39,5 +39,7 @@
        IRepository<Dt_Task> Repository { get; }
        Task<WebResponseContent> RequestInboundTask(string palletCode, string stationCode);
        Task<WebResponseContent> TaskCompleted(string taskNum);
    }
}
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_InboundService/InboundOrderService.cs
@@ -179,6 +179,7 @@
            }
            catch (Exception ex)
            {
                _unitOfWorkManage.RollbackTran();
                return WebResponseContent.Instance.Error(ex.Message);
            }
        }
@@ -211,6 +212,7 @@
            }
            catch (Exception ex)
            {
                _unitOfWorkManage.RollbackTran();
                return WebResponseContent.Instance.Error(ex.Message);
            }
        }
@@ -337,6 +339,7 @@
                        StockQuantity = item.BarcodeQty,
                        Status = 0,
                        OrderNo = inboundOrder.InboundOrderNo,
                        BusinessType=inboundOrder.BusinessType,
                    });
                    item.ReceiptQuantity = item.BarcodeQty;
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_Model/Models/Allocate/Dt_ AllocateOrder.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,18 @@
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WIDESEA_Core.DB.Models;
namespace WIDESEA_Model.Models.Allocate
{
    /// <summary>
    ///
    /// </summary>
    [SugarTable(nameof(Dt_InboundOrder), "入库单")]
    public class Dt_AllocateOrder : BaseEntity
    {
    }
}
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_Model/Models/Allocate/Dt_AllocateOrderDetail.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WIDESEA_Model.Models.Allocate
{
    public class Dt_AllocateOrderDetail
    {
    }
}
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_Model/Models/Basic/DT_DailySequence.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,35 @@
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WIDESEA_Core.DB.Models;
namespace WIDESEA_Model.Models.Basic
{
    /// <summary>
    ///
    /// </summary>
    [SugarTable("DT_DailySequence")]
    public class DT_DailySequence : BaseEntity
    {
        /// <summary>
        ///
        /// </summary>
        [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
        public long Id { get; set; }
        [SugarColumn(IsNullable = false)]
        public DateTime SequenceDate { get; set; }
        [SugarColumn(Length = 50, IsNullable = false)]
        public string SequenceKey { get; set; } = "MESBarcode";
        [SugarColumn(IsNullable = false)]
        public int CurrentValue { get; set; }
    }
}
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_Model/Models/Stock/Dt_StockInfoDetail.cs
@@ -118,6 +118,14 @@
        [SugarColumn(ColumnName = "barcode", ColumnDescription = "条码")]
        public string? Barcode { get; set; }
        /// <summary>
        /// å¤‡  æ³¨:业务类型
        /// é»˜è®¤å€¼:
        ///</summary>
        [SugarColumn(ColumnName = "businessType", ColumnDescription = "业务类型")]
        public string? BusinessType { get; set; }
        /// <summary>
        /// å¤‡æ³¨
        /// </summary>
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_Model/Models/TaskInfo/Dt_Task.cs
@@ -42,7 +42,7 @@
        public string PalletCode { get; set; }
        /// <summary>
        /// æ‰˜ç›˜ç±»åž‹
        /// æ‰˜ç›˜ç±»åž‹ -1 ç©ºæ‰˜ç›˜
        /// </summary>
        [SugarColumn(IsNullable = false, ColumnDescription = "托盘类型")]
        public int PalletType { get; set; }
@@ -119,6 +119,8 @@
        [SugarColumn(IsNullable = true, Length = 50, ColumnDescription = "单据编号")]
        public string? OrderNo { get; set; }
        /// <summary>
        /// ä¼˜å…ˆçº§
        /// </summary>
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundOrderService.cs
@@ -143,6 +143,7 @@
            }
            catch (Exception ex)
            {
                _unitOfWorkManage.RollbackTran();
                return WebResponseContent.Instance.Error(ex.Message);
            }
        }
@@ -173,6 +174,7 @@
            }
            catch (Exception ex)
            {
                _unitOfWorkManage.RollbackTran();
                return WebResponseContent.Instance.Error(ex.Message);
            }
        }
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService.cs
@@ -21,7 +21,10 @@
using Newtonsoft.Json;
using Org.BouncyCastle.Asn1.Ocsp;
using SqlSugar;
using System.Reflection;
using System.Reflection.Emit;
using System.Threading.Tasks;
using System.Xml.Linq;
using WIDESEA_Common.CommonEnum;
using WIDESEA_Common.LocationEnum;
using WIDESEA_Common.OrderEnum;
@@ -31,6 +34,7 @@
using WIDESEA_Core;
using WIDESEA_Core.BaseRepository;
using WIDESEA_Core.BaseServices;
using WIDESEA_Core.Enums;
using WIDESEA_Core.Helper;
using WIDESEA_DTO.Basic;
using WIDESEA_DTO.Task;
@@ -53,8 +57,11 @@
        private readonly IRepository<Dt_StockInfo> _stockRepository;
        private readonly ILocationInfoService _locationInfoService;
        private readonly IInboundOrderService _inboundOrderService;
        private readonly IInboundOrderDetailService _inboundOrderDetailService;
        private readonly ILocationStatusChangeRecordService _locationStatusChangeRecordService;
        private readonly IESSApiService _eSSApiService;
        private readonly IStockService _stockService;
        private readonly IRecordService _recordService;
        public IRepository<Dt_Task> Repository => BaseDal;
        private Dictionary<string, SqlSugar.OrderByType> _taskOrderBy = new()
@@ -66,15 +73,15 @@
        private Dictionary<string, string> stations = new Dictionary<string, string>
        {
            {"3-5","3-9" },
             {"2-5","2-9" },
              {"1-11","1-1" },
            {"2-5","2-9" },
            {"1-11","1-1" },
        };
        public List<int> TaskTypes => typeof(TaskTypeEnum).GetEnumIndexList();
        public List<int> TaskOutboundTypes => typeof(TaskTypeEnum).GetEnumIndexList();
        public TaskService(IRepository<Dt_Task> BaseDal, IMapper mapper, IUnitOfWorkManage unitOfWorkManage, IRepository<Dt_StockInfo> stockRepository, ILocationInfoService locationInfoService, IInboundOrderService inboundOrderService, ILocationStatusChangeRecordService locationStatusChangeRecordService, IESSApiService eSSApiService, ILogger<TaskService> logger) : base(BaseDal)
        public TaskService(IRepository<Dt_Task> BaseDal, IMapper mapper, IUnitOfWorkManage unitOfWorkManage, IRepository<Dt_StockInfo> stockRepository, ILocationInfoService locationInfoService, IInboundOrderService inboundOrderService, ILocationStatusChangeRecordService locationStatusChangeRecordService, IESSApiService eSSApiService, ILogger<TaskService> logger, IStockService stockService, IRecordService recordService, IInboundOrderDetailService inboundOrderDetailService) : base(BaseDal)
        {
            _mapper = mapper;
            _unitOfWorkManage = unitOfWorkManage;
@@ -84,247 +91,9 @@
            _locationStatusChangeRecordService = locationStatusChangeRecordService;
            _eSSApiService = eSSApiService;
            _logger = logger;
        }
        public async Task<WebResponseContent> RequestInboundTask(string palletCode, string stationCode)
        {
            try
            {
                Dt_Task dbtask = Repository.QueryFirst(x => x.PalletCode == palletCode);
                if (dbtask != null)
                {
                    return WebResponseContent.Instance.Error($"该托盘已生成任务");
                }
                Dt_StockInfo stockInfo = _stockRepository.Db.Queryable<Dt_StockInfo>().Where(x => x.PalletCode == palletCode).Includes(x => x.Details).First();
                if (stockInfo == null)
                {
                    return WebResponseContent.Instance.Error($"未找到组盘信息");
                }
                if (stockInfo.StockStatus != StockStatusEmun.组盘暂存.ObjToInt() && stockInfo.StockStatus != StockStatusEmun.手动组盘暂存.ObjToInt() && stockInfo.StockStatus != StockStatusEmun.拣选完成.ObjToInt())
                {
                    return WebResponseContent.Instance.Error($"该托盘状态不正确,不可申请入库");
                }
                if (!string.IsNullOrEmpty(stockInfo.LocationCode))
                {
                    return WebResponseContent.Instance.Error($"该托盘已绑定货位");
                }
                Dt_LocationInfo? locationInfo = _locationInfoService.AssignLocation();
                if (locationInfo == null)
                {
                    return WebResponseContent.Instance.Error($"货位分配失败,未找到可分配货位");
                }
                var newTask = new Dt_Task()
                {
                    CurrentAddress = stationCode,
                    Grade = 0,
                    NextAddress = stations.GetValueOrDefault(stationCode) ?? "",
                    PalletCode = palletCode,
                    Roadway = locationInfo.RoadwayNo,
                    SourceAddress = stationCode,
                    TargetAddress = locationInfo.LocationCode,
                    TaskType = TaskTypeEnum.Inbound.ObjToInt(),
                    TaskStatus = TaskStatusEnum.New.ObjToInt(),
                    WarehouseId = stockInfo.WarehouseId,
                    PalletType = stockInfo.PalletType,
                };
                if (stockInfo.PalletType == PalletTypeEnum.Empty.ObjToInt())
                {
                    _unitOfWorkManage.BeginTran();
                    int taskId = BaseDal.AddData(newTask);
                    newTask.TaskId = taskId;
                    locationInfo.LocationStatus = LocationStatusEnum.Lock.ObjToInt();
                    _locationInfoService.UpdateData(locationInfo);
                    stockInfo.StockStatus = StockStatusEmun.入库确认.ObjToInt();
                    _stockRepository.UpdateData(stockInfo);
                    _unitOfWorkManage.CommitTran();
                }
                else
                {
                    //获取是否存在入库单
                    Dt_InboundOrder? inboundOrder = null;
                    if (stockInfo != null && stockInfo.Details.Count > 0)
                    {
                        string? orderNo = stockInfo.Details.FirstOrDefault()?.OrderNo ?? "";
                        inboundOrder = _inboundOrderService.Repository.QueryFirst(x => x.InboundOrderNo == orderNo && x.OrderStatus < InOrderStatusEnum.入库完成.ObjToInt());
                    }
                    if (inboundOrder != null)
                    {
                        if (inboundOrder.OrderType == InOrderTypeEnum.Allocat.ObjToInt())
                        {
                            newTask.TaskType = TaskTypeEnum.InAllocate.ObjToInt();
                        }
                        else if (inboundOrder.OrderType == InOrderTypeEnum.Return.ObjToInt())
                        {
                            newTask.TaskType = TaskTypeEnum.ProductionReturn.ObjToInt();
                        }
                    }
                    if (stockInfo.StockStatus == StockStatusEmun.手动组盘暂存.ObjToInt())
                    {
                        stockInfo.StockStatus = StockStatusEmun.手动组盘入库确认.ObjToInt();
                    }
                    else if (stockInfo.StockStatus == StockStatusEmun.MES退库.ObjToInt())
                    {
                        newTask.TaskType = TaskTypeEnum.MesMatReturn.ObjToInt();
                    }
                    else if (stockInfo.StockStatus == StockStatusEmun.拣选完成.ObjToInt())
                    {
                        stockInfo.StockStatus = StockStatusEmun.入库确认.ObjToInt();
                        newTask.TaskType = TaskTypeEnum.InPick.ObjToInt();
                    }
                    else if (stockInfo.StockStatus == StockStatusEmun.送检库存完成.ObjToInt())
                    {
                        stockInfo.StockStatus = StockStatusEmun.手动组盘入库确认.ObjToInt();
                        newTask.TaskType = TaskTypeEnum.InQuality.ObjToInt();
                    }
                    else if (stockInfo.StockStatus == StockStatusEmun.盘点库存完成.ObjToInt())
                    {
                        stockInfo.StockStatus = StockStatusEmun.手动组盘入库确认.ObjToInt();
                        newTask.TaskType = TaskTypeEnum.InInventory.ObjToInt();
                    }
                    else
                    {
                        stockInfo.StockStatus = StockStatusEmun.入库确认.ObjToInt();
                    }
                    LocationStatusEnum lastStatus = (LocationStatusEnum)locationInfo.LocationStatus;
                    _unitOfWorkManage.BeginTran();
                    int taskId = BaseDal.AddData(newTask);
                    newTask.TaskId = taskId;
                    _locationStatusChangeRecordService.AddLocationStatusChangeRecord(locationInfo, locationInfo.LocationStatus, StockChangeType.Inbound.ObjToInt(), inboundOrder.InboundOrderNo, newTask.TaskNum);
                    locationInfo.LocationStatus = LocationStatusEnum.Lock.ObjToInt();
                    _locationInfoService.UpdateData(locationInfo);
                    _stockRepository.UpdateData(stockInfo);
                    _unitOfWorkManage.CommitTran();
                }
                TaskModel esstask = new TaskModel()
                {
                    taskType = "putaway",
                    taskGroupCode = "",
                    groupPriority = 0,
                    tasks = new List<TasksType>
                    {
                            new()
                            {
                                taskCode=newTask.TaskNum.ToString(),
                                taskPriority=0,
                                taskDescribe=new TaskDescribeType{
                                containerCode=palletCode,
                                containerType= "CT_KUBOT_STANDARD",
                                fromLocationCode=stations.GetValueOrDefault(stationCode)??"",
                                toStationCode="",
                                toLocationCode=locationInfo.LocationCode,
                                deadline=0,storageTag=""
                                }
                            }
                    }
                };
                _logger.LogInformation("创建任务Request:  " + JsonConvert.SerializeObject(esstask));
                var result = await _eSSApiService.CreateTaskAsync(esstask);
                _logger.LogInformation("创建任务返回:  " + result);
                if (result)
                {
                    return WebResponseContent.Instance.OK();
                }
                else
                {
                    return WebResponseContent.Instance.Error("下发机器人任务失败!");
                }
            }
            catch (Exception ex)
            {
                return WebResponseContent.Instance.Error(ex.Message);
            }
        }
        /// <summary>
        /// å…¥ç©ºç®±
        /// </summary>
        /// <param name="palletCode"></param>
        /// <param name="address"></param>
        /// <param name="WarehouseId"></param>
        /// <returns></returns>
        public WebResponseContent InEmpty(string palletCode, string address, int WarehouseId)
        {
            try
            {
                Dt_Task dbtask = Repository.QueryFirst(x => x.PalletCode == palletCode);
                if (dbtask != null)
                {
                    return WebResponseContent.Instance.Error($"该托盘已生成任务");
                }
                Dt_StockInfo stockInfo = _stockRepository.Db.Queryable<Dt_StockInfo>().Where(x => x.PalletCode == palletCode).First();
                if (stockInfo == null)
                {
                    return WebResponseContent.Instance.Error($"未找到组盘信息");
                }
                if (stockInfo.StockStatus != StockStatusEmun.组盘暂存.ObjToInt() && stockInfo.StockStatus != StockStatusEmun.手动组盘暂存.ObjToInt() && stockInfo.StockStatus != StockStatusEmun.拣选完成.ObjToInt())
                {
                    return WebResponseContent.Instance.Error($"该托盘状态不正确,不可申请入库");
                }
                if (!string.IsNullOrEmpty(stockInfo.LocationCode))
                {
                    return WebResponseContent.Instance.Error($"该托盘已绑定货位");
                }
                //stockInfo = new Dt_StockInfo()
                //{
                //    PalletCode = barcode,
                //    StockStatus = StockStatusEmun.入库确认.ObjToInt(),
                //    WarehouseId = WarehouseId,
                //    PalletType = PalletTypeEnum.Empty.ObjToInt(),
                //    Details = new List<Dt_StockInfoDetail>()
                //};
                var locationInfo = _locationInfoService.AssignLocation();
                if (locationInfo == null)
                {
                    return WebResponseContent.Instance.Error($"货位分配失败,未找到可分配货位");
                }
                Dt_Task newTask = new Dt_Task()
                {
                    CurrentAddress = address,
                    Grade = 0,
                    NextAddress = locationInfo.LocationCode,
                    PalletCode = palletCode,
                    Roadway = locationInfo.RoadwayNo,
                    SourceAddress = address,
                    TargetAddress = locationInfo.LocationCode,
                    TaskType = TaskTypeEnum.InEmpty.ObjToInt(),
                    TaskStatus = TaskStatusEnum.New.ObjToInt(),
                    WarehouseId = stockInfo.WarehouseId,
                    PalletType = stockInfo.PalletType
                };
                locationInfo.LocationStatus = LocationStatusEnum.Lock.ObjToInt();
                _unitOfWorkManage.BeginTran();
                int taskId = BaseDal.AddData(newTask);
                newTask.TaskId = taskId;
                _locationInfoService.UpdateData(locationInfo);
                stockInfo.StockStatus = StockStatusEmun.入库确认.ObjToInt();
                _stockRepository.AddData(stockInfo);
                _unitOfWorkManage.CommitTran();
                return WebResponseContent.Instance.OK();
            }
            catch (Exception ex)
            {
                _unitOfWorkManage.RollbackTran();
                return WebResponseContent.Instance.Error(ex.Message);
            }
            _stockService = stockService;
            _recordService = recordService;
            _inboundOrderDetailService = inboundOrderDetailService;
        }
        /// <summary>
@@ -332,22 +101,151 @@
        /// </summary>
        /// <param name="taskNum"></param>
        /// <returns></returns>
        public async Task<WebResponseContent> TaskCompleted(int taskNum)
        public async Task<WebResponseContent> TaskCompleted(string taskNum)
        {
            try
            {
                Dt_Task task;
                if (int.TryParse(taskNum, out var newTaskNum))
                {
                    task = BaseDal.QueryFirst(x => x.TaskNum == newTaskNum);
                    if (task == null)
                    {
                        return WebResponseContent.Instance.Error("未找到任务信息");
                    }
                }
                else
                {
                    return WebResponseContent.Instance.Error("未找到任务信息");
                }
                MethodInfo? methodInfo = GetType().GetMethod(((TaskTypeEnum)task.TaskType) + "TaskCompleted");
                if (methodInfo != null)
                {
                    WebResponseContent? responseContent = (WebResponseContent?)methodInfo.Invoke(this, new object[] { task });
                    if (responseContent != null)
                    {
                        return responseContent;
                    }
                }
                return WebResponseContent.Instance.Error("未找到任务类型对应业务处理逻辑");
            }
            catch (Exception ex)
            {
                return WebResponseContent.Instance.Error(ex.Message);
            }
        }
        /// <summary>
        /// å…¥åº“完成
        /// </summary>
        /// <param name="task"></param>
        /// <returns></returns>
        public WebResponseContent InboundTaskCompleted(Dt_Task task)
        {
            decimal beforeQuantity = 0;
            //查库存
            Dt_StockInfo stockInfo = _stockRepository.Db.Queryable<Dt_StockInfo>().Where(x => x.PalletCode == task.PalletCode && x.WarehouseId == task.WarehouseId).First();
            if (stockInfo == null)
            {
                return WebResponseContent.Instance.Error($"未找到托盘对应的组盘信息");
            }
            if (stockInfo.Details.Count == 0 && stockInfo.PalletType != PalletTypeEnum.Empty.ObjToInt())
            {
                return WebResponseContent.Instance.Error($"未找到该托盘库存明细信息");
            }
            //查货位
            Dt_LocationInfo locationInfo = _locationInfoService.Repository.QueryFirst(x => x.LocationCode == task.TargetAddress);
            if (locationInfo == null)
            {
                return WebResponseContent.Instance.Error($"未找到对应的终点货位信息");
            }
            var ordernos = stockInfo.Details.GroupBy(x => x.OrderNo).Select(o => o.Key).ToList();
            var inboundOrders = _inboundOrderService.Repository.Db.Queryable<Dt_InboundOrder>().Where(x => ordernos.Contains(x.InboundOrderNo)).Includes(x => x.Details).ToList();
            Dt_InboundOrderDetail? inboundOrderDetail = null;
            foreach (var inboundOrder in inboundOrders)
            {
                //标准入库流程查找入库单据
                if (inboundOrder != null && stockInfo.StockStatus == StockStatusEmun.入库确认.ObjToInt())
                {
                    foreach (var item in stockInfo.Details.Where(x => x.OrderNo == inboundOrder.InboundOrderNo).ToList())
                    {
                        var inbounddetail = inboundOrder.Details.Where(x => x.lineNo == item.InboundOrderRowNo && x.Barcode == item.Barcode).FirstOrDefault();
                        if (inbounddetail != null)
                        {
                            inbounddetail.OverInQuantity += item.StockQuantity;
                            if (inbounddetail.OverInQuantity == inbounddetail.OrderQuantity)
                            {
                                inbounddetail.OrderDetailStatus = OrderDetailStatusEnum.Over.ObjToInt();
                            }
                            else if (inbounddetail.OrderDetailStatus == OrderDetailStatusEnum.New.ObjToInt())
                            {
                                inbounddetail.OrderDetailStatus = OrderDetailStatusEnum.Inbounding.ObjToInt();
                            }
                            _inboundOrderDetailService.UpdateData(inbounddetail);
                        }
                    }
                    if (inboundOrder.Details.Count == inboundOrder.Details.Where(x => x.OrderQuantity == x.OverInQuantity).Count())
                    {
                        inboundOrder.OrderStatus = InOrderStatusEnum.入库完成.ObjToInt();
                    }
                    else if (inboundOrder.OrderStatus == InOrderStatusEnum.未开始.ObjToInt())
                    {
                        inboundOrder.OrderStatus = InOrderStatusEnum.入库中.ObjToInt();
                    }
                    _inboundOrderService.UpdateData(inboundOrder);
                }
            }
            stockInfo.LocationCode = task.TargetAddress;
            stockInfo.StockStatus = StockStatusEmun.入库完成.ObjToInt();
            stockInfo.Details.ForEach(x =>
            {
                x.Status = StockStatusEmun.入库完成.ObjToInt();
            });
            _stockService.StockInfoService.Repository.UpdateData(stockInfo);
            _stockService.StockInfoDetailService.Repository.UpdateData(stockInfo.Details);
            beforeQuantity = stockInfo.Details.Where(x => x.Id != 0).Sum(x => x.StockQuantity);
            int beforeStatus = locationInfo.LocationStatus;
            if (stockInfo.PalletType == PalletTypeEnum.Empty.ObjToInt())
            {
                locationInfo.LocationStatus = LocationStatusEnum.Pallet.ObjToInt();
            }
            else
            {
                locationInfo.LocationStatus = LocationStatusEnum.InStock.ObjToInt();
            }
            _locationInfoService.Repository.UpdateData(locationInfo);
            task.TaskStatus = TaskStatusEnum.Finish.ObjToInt();
            BaseDal.DeleteAndMoveIntoHty(task, App.User.UserId == 0 ? OperateTypeEnum.自动完成 : OperateTypeEnum.人工完成);
            _locationStatusChangeRecordService.AddLocationStatusChangeRecord(locationInfo, beforeStatus, StockChangeType.Inbound.ObjToInt(), "", task.TaskNum);
            _recordService.StockQuantityChangeRecordService.AddStockChangeRecord(stockInfo, stockInfo.Details, beforeQuantity, stockInfo.Details.Sum(x => x.StockQuantity) + beforeQuantity, WIDESEA_Common.StockEnum.StockChangeType.MaterielGroup);
            return WebResponseContent.Instance.OK();
        }
        public async Task<WebResponseContent> InEmptyTaskCompleted(Dt_Task task)
        {
            WebResponseContent content = new WebResponseContent();
            try
            {
                Dt_Task task = await Repository.QueryFirstAsync(x => x.TaskNum == taskNum);
                if (task == null)
                {
                    return await Task.FromResult(WebResponseContent.Instance.Error($"未找到任务信息"));
                }
                Dt_LocationInfo locationInfo = _locationInfoService.Repository.QueryFirst(x => x.LocationCode == task.TargetAddress);
                if (locationInfo == null)
                {
                    return content.Error($"未找到对应的终点货位信息");
                }
                Dt_StockInfo stockInfo = _stockRepository.Db.Queryable<Dt_StockInfo>().Where(x => x.PalletCode == task.PalletCode && x.WarehouseId == task.WarehouseId).Includes(x => x.Details).First();
                Dt_StockInfo stockInfo = _stockRepository.Db.Queryable<Dt_StockInfo>().Where(x => x.PalletCode == task.PalletCode && x.WarehouseId == task.WarehouseId).First();
                if (stockInfo == null)
                {
                    return WebResponseContent.Instance.Error($"未找到托盘对应的组盘信息");
@@ -361,13 +259,24 @@
                {
                    return WebResponseContent.Instance.Error($"货位状态不正确");
                }
                LocationStatusEnum lastStatus = (LocationStatusEnum)locationInfo.LocationStatus;
                locationInfo.LocationStatus = LocationStatusEnum.InStock.ObjToInt();
                var beforelocationStatus = locationInfo.LocationStatus;
                locationInfo.LocationStatus = LocationStatusEnum.Pallet.ObjToInt();
                _locationInfoService.Repository.UpdateData(locationInfo);
                stockInfo.LocationCode = locationInfo.LocationCode;
                stockInfo.PalletCode = task.PalletCode;
                stockInfo.LocationCode = task.TargetAddress;
                stockInfo.StockStatus = StockStatusEmun.入库完成.ObjToInt();
                _stockRepository.UpdateData(stockInfo);
                Dt_InboundOrder? inboundOrder = _inboundOrderService.Repository.Db.Queryable<Dt_InboundOrder>().Where(x => x.InboundOrderNo == stockInfo.Details.FirstOrDefault().OrderNo).Includes(x => x.Details).First();
                Dt_InboundOrderDetail? inboundOrderDetail = null;
                task.TaskStatus = TaskStatusEnum.Finish.ObjToInt();
                BaseDal.DeleteAndMoveIntoHty(task, App.User.UserId == 0 ? WIDESEA_Core.Enums.OperateTypeEnum.自动完成 : OperateTypeEnum.人工完成);
                _locationStatusChangeRecordService.AddLocationStatusChangeRecord(locationInfo, beforelocationStatus, StockChangeType.Inbound.ObjToInt(), "", task.TaskNum);
                return content;
            }
@@ -376,5 +285,49 @@
                return await Task.FromResult(WebResponseContent.Instance.Error(ex.Message));
            }
        }
        public async Task<WebResponseContent> OutEmptyTaskCompleted(Dt_Task task)
        {
            WebResponseContent content = new WebResponseContent();
            try
            {
                Dt_StockInfo stockInfo = _stockRepository.Db.Queryable<Dt_StockInfo>().Where(x => x.PalletCode == task.PalletCode && x.WarehouseId == task.WarehouseId).First();
                if (stockInfo == null)
                {
                    return WebResponseContent.Instance.Error($"未找到托盘对应的库存信息");
                }
                Dt_LocationInfo locationInfo = _locationInfoService.Repository.QueryFirst(x => x.LocationCode == task.SourceAddress);
                if (locationInfo == null)
                {
                    return content.Error($"未找到对应的终点货位信息");
                }
                _stockRepository.Db.Deleteable(stockInfo);
                int beforeStatus = locationInfo.LocationStatus;
                locationInfo.LocationStatus = LocationStatusEnum.Free.ObjToInt();
                _locationInfoService.Repository.UpdateData(locationInfo);
                task.TaskStatus = TaskStatusEnum.Finish.ObjToInt();
                BaseDal.DeleteAndMoveIntoHty(task, App.User.UserId == 0 ? OperateTypeEnum.自动完成 : OperateTypeEnum.人工完成);
                _stockService.StockInfoService.Repository.DeleteAndMoveIntoHty(stockInfo, App.User.UserId == 0 ? OperateTypeEnum.自动完成 : OperateTypeEnum.人工完成);
                _locationStatusChangeRecordService.AddLocationStatusChangeRecord(locationInfo, beforeStatus, StockChangeType.Outbound.ObjToInt(), stockInfo.Details.FirstOrDefault()?.OrderNo ?? "", task.TaskNum);
                return WebResponseContent.Instance.OK();
            }
            catch (Exception ex)
            {
                return await Task.FromResult(WebResponseContent.Instance.Error(ex.Message));
            }
        }
    }
}
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService_Inbound.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,233 @@
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WIDESEA_Common.CommonEnum;
using WIDESEA_Common.LocationEnum;
using WIDESEA_Common.OrderEnum;
using WIDESEA_Common.StockEnum;
using WIDESEA_Common.TaskEnum;
using WIDESEA_Core;
using WIDESEA_Core.Helper;
using WIDESEA_DTO.Basic;
using WIDESEA_Model.Models;
namespace WIDESEA_TaskInfoService
{
    public partial class TaskService
    {
        public async Task<WebResponseContent> RequestInboundTask(string palletCode, string stationCode)
        {
            try
            {
                Dt_Task dbtask = Repository.QueryFirst(x => x.PalletCode == palletCode);
                if (dbtask != null)
                {
                    return WebResponseContent.Instance.Error($"该托盘已生成任务");
                }
                Dt_StockInfo stockInfo = _stockRepository.Db.Queryable<Dt_StockInfo>().Where(x => x.PalletCode == palletCode).Includes(x => x.Details).First();
                if (stockInfo == null)
                {
                    return WebResponseContent.Instance.Error($"未找到组盘信息");
                }
                if (stockInfo.StockStatus != StockStatusEmun.组盘暂存.ObjToInt() && stockInfo.StockStatus != StockStatusEmun.手动组盘暂存.ObjToInt() && stockInfo.StockStatus != StockStatusEmun.拣选完成.ObjToInt())
                {
                    return WebResponseContent.Instance.Error($"该托盘状态不正确,不可申请入库");
                }
                if (!string.IsNullOrEmpty(stockInfo.LocationCode))
                {
                    return WebResponseContent.Instance.Error($"该托盘已绑定货位");
                }
                Dt_LocationInfo? locationInfo = _locationInfoService.AssignLocation();
                if (locationInfo == null)
                {
                    return WebResponseContent.Instance.Error($"货位分配失败,未找到可分配货位");
                }
                var newTask = new Dt_Task()
                {
                    CurrentAddress = stationCode,
                    Grade = 0,
                    NextAddress = stations.GetValueOrDefault(stationCode) ?? "",
                    PalletCode = palletCode,
                    Roadway = locationInfo.RoadwayNo,
                    SourceAddress = stationCode,
                    TargetAddress = locationInfo.LocationCode,
                    TaskType = TaskTypeEnum.Inbound.ObjToInt(),
                    TaskStatus = TaskStatusEnum.New.ObjToInt(),
                    WarehouseId = stockInfo.WarehouseId,
                    PalletType = stockInfo.PalletType,
                };
                //空箱
                if (stockInfo.PalletType == PalletTypeEnum.Empty.ObjToInt())
                {
                    _unitOfWorkManage.BeginTran();
                    newTask.TaskType = TaskTypeEnum.InEmpty.ObjToInt();
                    int taskId = BaseDal.AddData(newTask);
                    newTask.TaskId = taskId;
                    locationInfo.LocationStatus = LocationStatusEnum.Lock.ObjToInt();
                    _locationInfoService.UpdateData(locationInfo);
                    stockInfo.StockStatus = StockStatusEmun.入库确认.ObjToInt();
                    _stockRepository.UpdateData(stockInfo);
                    _unitOfWorkManage.CommitTran();
                }
                else
                {
                    //获取是否存在入库单
                    Dt_InboundOrder? inboundOrder = null;
                    if (stockInfo != null && stockInfo.Details.Count > 0)
                    {
                        string? orderNo = stockInfo.Details.FirstOrDefault()?.OrderNo ?? "";
                        inboundOrder = _inboundOrderService.Repository.QueryFirst(x => x.InboundOrderNo == orderNo && x.OrderStatus < InOrderStatusEnum.入库完成.ObjToInt());
                    }
                    stockInfo.StockStatus = StockStatusEmun.入库确认.ObjToInt();
                    LocationStatusEnum lastStatus = (LocationStatusEnum)locationInfo.LocationStatus;
                    _unitOfWorkManage.BeginTran();
                    int taskId = BaseDal.AddData(newTask);
                    newTask.TaskId = taskId;
                    _locationStatusChangeRecordService.AddLocationStatusChangeRecord(locationInfo, locationInfo.LocationStatus, StockChangeType.Inbound.ObjToInt(), inboundOrder?.InboundOrderNo, newTask.TaskNum);
                    locationInfo.LocationStatus = LocationStatusEnum.Lock.ObjToInt();
                    _locationInfoService.UpdateData(locationInfo);
                    _stockRepository.UpdateData(stockInfo);
                    _unitOfWorkManage.CommitTran();
                }
                TaskModel esstask = new TaskModel()
                {
                    taskType = "putaway",
                    taskGroupCode = "",
                    groupPriority = 0,
                    tasks = new List<TasksType>
                    {
                            new()
                            {
                                taskCode=newTask.TaskNum.ToString(),
                                taskPriority=0,
                                taskDescribe=new TaskDescribeType{
                                containerCode=palletCode,
                                containerType= "CT_KUBOT_STANDARD",
                                fromLocationCode=stations.GetValueOrDefault(stationCode)??"",
                                toStationCode="",
                                toLocationCode=locationInfo.LocationCode,
                                deadline=0,storageTag=""
                                }
                            }
                    }
                };
                _logger.LogInformation("创建任务Request:  " + JsonConvert.SerializeObject(esstask));
                var result = await _eSSApiService.CreateTaskAsync(esstask);
                _logger.LogInformation("创建任务返回:  " + result);
                if (result)
                {
                    return WebResponseContent.Instance.OK();
                }
                else
                {
                    return WebResponseContent.Instance.Error("下发机器人任务失败!");
                }
            }
            catch (Exception ex)
            {
                return WebResponseContent.Instance.Error(ex.Message);
            }
        }
        /// <summary>
        /// å…¥ç©ºç®±
        /// </summary>
        /// <param name="palletCode"></param>
        /// <param name="address"></param>
        /// <param name="WarehouseId"></param>
        /// <returns></returns>
        public WebResponseContent InEmpty(string palletCode, string address, int WarehouseId)
        {
            try
            {
                Dt_Task dbtask = Repository.QueryFirst(x => x.PalletCode == palletCode);
                if (dbtask != null)
                {
                    return WebResponseContent.Instance.Error($"该托盘已生成任务");
                }
                Dt_StockInfo stockInfo = _stockRepository.Db.Queryable<Dt_StockInfo>().Where(x => x.PalletCode == palletCode).First();
                if (stockInfo == null)
                {
                    return WebResponseContent.Instance.Error($"未找到组盘信息");
                }
                if (stockInfo.StockStatus != StockStatusEmun.组盘暂存.ObjToInt() && stockInfo.StockStatus != StockStatusEmun.手动组盘暂存.ObjToInt() && stockInfo.StockStatus != StockStatusEmun.拣选完成.ObjToInt())
                {
                    return WebResponseContent.Instance.Error($"该托盘状态不正确,不可申请入库");
                }
                if (!string.IsNullOrEmpty(stockInfo.LocationCode))
                {
                    return WebResponseContent.Instance.Error($"该托盘已绑定货位");
                }
                //stockInfo = new Dt_StockInfo()
                //{
                //    PalletCode = barcode,
                //    StockStatus = StockStatusEmun.入库确认.ObjToInt(),
                //    WarehouseId = WarehouseId,
                //    PalletType = PalletTypeEnum.Empty.ObjToInt(),
                //    Details = new List<Dt_StockInfoDetail>()
                //};
                var locationInfo = _locationInfoService.AssignLocation();
                if (locationInfo == null)
                {
                    return WebResponseContent.Instance.Error($"货位分配失败,未找到可分配货位");
                }
                Dt_Task newTask = new Dt_Task()
                {
                    CurrentAddress = address,
                    Grade = 0,
                    NextAddress = locationInfo.LocationCode,
                    PalletCode = palletCode,
                    Roadway = locationInfo.RoadwayNo,
                    SourceAddress = address,
                    TargetAddress = locationInfo.LocationCode,
                    TaskType = TaskTypeEnum.InEmpty.ObjToInt(),
                    TaskStatus = TaskStatusEnum.New.ObjToInt(),
                    WarehouseId = stockInfo.WarehouseId,
                    PalletType = stockInfo.PalletType
                };
                locationInfo.LocationStatus = LocationStatusEnum.Lock.ObjToInt();
                _unitOfWorkManage.BeginTran();
                int taskId = BaseDal.AddData(newTask);
                newTask.TaskId = taskId;
                _locationInfoService.UpdateData(locationInfo);
                stockInfo.StockStatus = StockStatusEmun.入库确认.ObjToInt();
                _stockRepository.AddData(stockInfo);
                _unitOfWorkManage.CommitTran();
                return WebResponseContent.Instance.OK();
            }
            catch (Exception ex)
            {
                _unitOfWorkManage.RollbackTran();
                return WebResponseContent.Instance.Error(ex.Message);
            }
        }
    }
}
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService_Outbound.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,126 @@
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WIDESEA_Common.CommonEnum;
using WIDESEA_Common.LocationEnum;
using WIDESEA_Common.OtherEnum;
using WIDESEA_Common.StockEnum;
using WIDESEA_Common.TaskEnum;
using WIDESEA_Core;
using WIDESEA_Core.Helper;
using WIDESEA_DTO.Basic;
using WIDESEA_Model.Models;
namespace WIDESEA_TaskInfoService
{
    public partial class TaskService
    {
        /// <summary>
        /// ç©ºæ‰˜ç›˜å‡ºåº“任务
        /// </summary>
        /// <param name="inTask"></param>
        /// <returns></returns>
        public async Task<WebResponseContent> PalletOutboundTask(string endStation, string palletCode = "")
        {
            try
            {
                Dt_StockInfo stockInfo ;
                if (string.IsNullOrEmpty(palletCode))
                {
                    stockInfo = _stockRepository.Db.Queryable<Dt_StockInfo>().Where(x => x.PalletType == PalletTypeEnum.Empty.ObjToInt()).First();
                }
                else
                {
                    stockInfo = _stockRepository.Db.Queryable<Dt_StockInfo>().Where(x => x.PalletCode == palletCode) .First();
                }
                if (stockInfo == null)
                {
                    return WebResponseContent.Instance.Error("未找到空托盘库存");
                }
                Dt_LocationInfo locationInfo = _locationInfoService.Repository.QueryFirst(x => x.LocationCode == stockInfo.LocationCode);
                if (locationInfo == null)
                {
                    return WebResponseContent.Instance.Error("未找到空托盘库存对应的货位信息");
                }
                Dt_Task task = new Dt_Task()
                {
                    CurrentAddress = stockInfo.LocationCode,
                    Grade = 0,
                    NextAddress = endStation,
                    PalletCode = stockInfo.PalletCode,
                    Roadway = locationInfo.RoadwayNo,
                    SourceAddress = stockInfo.LocationCode,
                    TargetAddress = endStation,
                    TaskStatus = TaskStatusEnum.New.ObjToInt(),
                    TaskType = TaskTypeEnum.OutEmpty.ObjToInt(),
                    WarehouseId = stockInfo.WarehouseId,
                    PalletType = stockInfo.PalletType
                };
                int beforeStatus = locationInfo.LocationStatus;
                _unitOfWorkManage.BeginTran();
                stockInfo.StockStatus = StockStatusEmun.出库锁定.ObjToInt();
                locationInfo.LocationStatus = LocationStatusEnum.Lock.ObjToInt();
                int taskId = BaseDal.AddData(task);
                task.TaskId = taskId;
                _stockService.StockInfoService.UpdateData(stockInfo);
                _locationInfoService.UpdateData(locationInfo);
                _recordService.LocationStatusChangeRecordSetvice.AddLocationStatusChangeRecord(locationInfo, beforeStatus, StockChangeType.Outbound.ObjToInt(), "", task.TaskNum);
                _unitOfWorkManage.CommitTran();
                TaskModel esstask = new TaskModel()
                {
                    taskType = "carry",
                    taskGroupCode = "",
                    groupPriority = 0,
                    tasks = new List<TasksType>
                    {
                            new()
                            {
                                taskCode=task.TaskNum.ToString(),
                                taskPriority=0,
                                taskDescribe=new TaskDescribeType{
                                containerCode=stockInfo.PalletCode,
                                containerType= "CT_KUBOT_STANDARD",
                                fromLocationCode=stockInfo.LocationCode??"",
                                toStationCode="",
                                toLocationCode=endStation,
                                deadline=0,storageTag=""
                                }
                            }
                    }
                };
                _logger.LogInformation("创建任务PalletOutboundTask Request:  " + JsonConvert.SerializeObject(esstask));
                var result = await _eSSApiService.CreateTaskAsync(esstask);
                _logger.LogInformation("创建任务PalletOutboundTask è¿”回:  " + result);
                if (result)
                {
                    return WebResponseContent.Instance.OK();
                }
                else
                {
                    return WebResponseContent.Instance.Error("下发机器人任务失败!");
                }
            }
            catch (Exception ex)
            {
                return WebResponseContent.Instance.Error(ex.Message);
            }
        }
    }
}
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_WMSServer.sln
@@ -68,6 +68,12 @@
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WIDESEA_CheckService", "WIDESEA_CheckService\WIDESEA_CheckService.csproj", "{C57C16CE-88A7-499A-8CE1-855D55482891}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Allocate", "Allocate", "{02EA681E-C7D8-13C7-8484-4AC65E1B71E8}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WIDESEA_AllocateService", "WIDESEA_AllocateService\WIDESEA_AllocateService.csproj", "{D35E0897-0E66-4E1E-B8DA-28701BE3B2B7}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WIDESEA_IAllocateService", "WIDESEA_IAllocateService\WIDESEA_IAllocateService.csproj", "{A6E822A3-5A09-4B18-BEE6-57CC7D7B8BEC}"
EndProject
Global
    GlobalSection(SolutionConfigurationPlatforms) = preSolution
        Debug|Any CPU = Debug|Any CPU
@@ -330,6 +336,30 @@
        {C57C16CE-88A7-499A-8CE1-855D55482891}.Release|Any CPU.Build.0 = Release|Any CPU
        {C57C16CE-88A7-499A-8CE1-855D55482891}.Release|x86.ActiveCfg = Release|Any CPU
        {C57C16CE-88A7-499A-8CE1-855D55482891}.Release|x86.Build.0 = Release|Any CPU
        {D35E0897-0E66-4E1E-B8DA-28701BE3B2B7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
        {D35E0897-0E66-4E1E-B8DA-28701BE3B2B7}.Debug|Any CPU.Build.0 = Debug|Any CPU
        {D35E0897-0E66-4E1E-B8DA-28701BE3B2B7}.Debug|x86.ActiveCfg = Debug|Any CPU
        {D35E0897-0E66-4E1E-B8DA-28701BE3B2B7}.Debug|x86.Build.0 = Debug|Any CPU
        {D35E0897-0E66-4E1E-B8DA-28701BE3B2B7}.Dev|Any CPU.ActiveCfg = Release|Any CPU
        {D35E0897-0E66-4E1E-B8DA-28701BE3B2B7}.Dev|Any CPU.Build.0 = Release|Any CPU
        {D35E0897-0E66-4E1E-B8DA-28701BE3B2B7}.Dev|x86.ActiveCfg = Release|Any CPU
        {D35E0897-0E66-4E1E-B8DA-28701BE3B2B7}.Dev|x86.Build.0 = Release|Any CPU
        {D35E0897-0E66-4E1E-B8DA-28701BE3B2B7}.Release|Any CPU.ActiveCfg = Release|Any CPU
        {D35E0897-0E66-4E1E-B8DA-28701BE3B2B7}.Release|Any CPU.Build.0 = Release|Any CPU
        {D35E0897-0E66-4E1E-B8DA-28701BE3B2B7}.Release|x86.ActiveCfg = Release|Any CPU
        {D35E0897-0E66-4E1E-B8DA-28701BE3B2B7}.Release|x86.Build.0 = Release|Any CPU
        {A6E822A3-5A09-4B18-BEE6-57CC7D7B8BEC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
        {A6E822A3-5A09-4B18-BEE6-57CC7D7B8BEC}.Debug|Any CPU.Build.0 = Debug|Any CPU
        {A6E822A3-5A09-4B18-BEE6-57CC7D7B8BEC}.Debug|x86.ActiveCfg = Debug|Any CPU
        {A6E822A3-5A09-4B18-BEE6-57CC7D7B8BEC}.Debug|x86.Build.0 = Debug|Any CPU
        {A6E822A3-5A09-4B18-BEE6-57CC7D7B8BEC}.Dev|Any CPU.ActiveCfg = Release|Any CPU
        {A6E822A3-5A09-4B18-BEE6-57CC7D7B8BEC}.Dev|Any CPU.Build.0 = Release|Any CPU
        {A6E822A3-5A09-4B18-BEE6-57CC7D7B8BEC}.Dev|x86.ActiveCfg = Release|Any CPU
        {A6E822A3-5A09-4B18-BEE6-57CC7D7B8BEC}.Dev|x86.Build.0 = Release|Any CPU
        {A6E822A3-5A09-4B18-BEE6-57CC7D7B8BEC}.Release|Any CPU.ActiveCfg = Release|Any CPU
        {A6E822A3-5A09-4B18-BEE6-57CC7D7B8BEC}.Release|Any CPU.Build.0 = Release|Any CPU
        {A6E822A3-5A09-4B18-BEE6-57CC7D7B8BEC}.Release|x86.ActiveCfg = Release|Any CPU
        {A6E822A3-5A09-4B18-BEE6-57CC7D7B8BEC}.Release|x86.Build.0 = Release|Any CPU
    EndGlobalSection
    GlobalSection(SolutionProperties) = preSolution
        HideSolutionNode = FALSE
@@ -359,6 +389,9 @@
        {294A53A4-1311-4B71-A812-378A2BCB8346} = {60DE2920-37C6-4C2B-A053-6B1B2DAF047A}
        {82EBBC95-FD6E-4E30-9F21-625DE1991C2C} = {294A53A4-1311-4B71-A812-378A2BCB8346}
        {C57C16CE-88A7-499A-8CE1-855D55482891} = {294A53A4-1311-4B71-A812-378A2BCB8346}
        {02EA681E-C7D8-13C7-8484-4AC65E1B71E8} = {60DE2920-37C6-4C2B-A053-6B1B2DAF047A}
        {D35E0897-0E66-4E1E-B8DA-28701BE3B2B7} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
        {A6E822A3-5A09-4B18-BEE6-57CC7D7B8BEC} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
    EndGlobalSection
    GlobalSection(ExtensibilityGlobals) = postSolution
        SolutionGuid = {599A7267-7402-4143-84AE-9B407FC2BB69}
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Allocate/AllocateOrderController.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,25 @@
using Microsoft.AspNetCore.Mvc;
using WIDESEA_Core.BaseController;
using WIDESEA_IAllocateService;
using WIDESEA_IInboundService;
using WIDESEA_Model.Models;
using WIDESEA_Model.Models.Allocate;
namespace WIDESEA_WMSServer.Controllers.Allocate
{
    /// <summary>
    /// è°ƒæ‹¨å•
    /// </summary>
    [Route("api/AllocateOrder")]
    [ApiController]
    public class AllocateOrderController : ApiBaseController<IAllocateService, Dt_AllocateOrder>
    {
        public AllocateOrderController(IAllocateService service) : base(service)
        {
        }
    }
}
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/ESSController.cs
@@ -1,5 +1,6 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Memory;
using Newtonsoft.Json;
using System.DirectoryServices.Protocols;
using System.Threading.Tasks;
@@ -24,10 +25,13 @@
        public readonly ITaskService _taskService;
        private readonly ILogger<ESSController> _logger;
        public ESSController(ITaskService taskService, ILogger<ESSController> logger)
        private readonly IMemoryCache _memoryCache;
        private static readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1);
        public ESSController(ITaskService taskService, ILogger<ESSController> logger, IMemoryCache memoryCache)
        {
            _taskService = taskService;
            _logger = logger;
            _memoryCache = memoryCache;
        }
        /// <summary>
@@ -38,6 +42,8 @@
        [HttpPost("ContainerArrivalReport"), AllowAnonymous]
        public async Task<IActionResult> ContainerArrivalReport([FromBody] ContainerArrivalRequest request)
        {
            //这里要判断出库的时候,料箱会到扫码处。也会请求这个接口。
            var response = new ApiResponse<ContainerArrivalResponseData>
            {
                Code = 0,
@@ -47,17 +53,69 @@
                    direction = "100" // ç¤ºä¾‹å€¼ï¼šå¯æ ¹æ®å®žé™…情况返回方向或其他信息
                }
            };
            var result = await _taskService.RequestInboundTask(request.ContainerCode, request.SlotCode);
            if (result.Status)
            // ç”Ÿæˆè¯·æ±‚的唯一标识(基于callId + æ—¶é—´æˆ³ï¼‰
            var requestKey = $"callback_{request.CallId}-{request.ContainerCode}_{DateTime.UtcNow:yyyyMMddHH}";
            // æ£€æŸ¥æ˜¯å¦å·²ç»å¤„理过相同的请求
            if (_memoryCache.TryGetValue(requestKey, out bool _))
            {
                return Ok(response);
            }
            else
            {
                _logger.LogWarning("检测到重复请求,已忽略: CallId={CallId}", request.CallId);
                response.Code = 1;
                response.Msg = "error";
                response.Data.direction = "0";
                return Ok(response);
                return Ok(response);
            }
            await _semaphore.WaitAsync();
            try
            {
                if (_memoryCache.TryGetValue(requestKey, out bool _))
                {
                    _logger.LogWarning("双重检查检测到重复请求,已忽略: CallId={CallId}", request.CallId);
                    response.Code = 1;
                    response.Msg = "error";
                    response.Data.direction = "0";
                    return Ok(response);
                }
                var result = await _taskService.RequestInboundTask(request.ContainerCode, request.SlotCode);
                var cacheOptions = new MemoryCacheEntryOptions
                {
                    AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(1)
                };
                _memoryCache.Set(requestKey, true, cacheOptions);
                if (result.Status)
                {
                    response = new ApiResponse<ContainerArrivalResponseData>
                    {
                        Code = 0,
                        Msg = "",
                        Data = new ContainerArrivalResponseData
                        {
                            direction = "100"
                        }
                    };
                    return Ok(response);
                }
                else
                {
                    response.Code = 1;
                    response.Msg = "error";
                    response.Data.direction = "0";
                    return Ok(response);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "处理任务状态回调时发生异常: CallId={CallId}", request.CallId);
                return Ok($"处理回调时发生异常: {ex.Message}");
            }
            finally
            {
                _semaphore.Release();
            }
        }
@@ -94,12 +152,6 @@
                // æ ¹æ®äº‹ä»¶ç±»åž‹å’ŒçŠ¶æ€è¿›è¡Œä¸åŒçš„ä¸šåŠ¡å¤„ç†
                switch (request.EventType)
                {
                    case EventType.task:
                        await HandleTaskStatusChange(request);
                        break;
                    case EventType.task_allocated:
                        await HandleTaskAllocated(request);
                        break;
                    case EventType.tote_load:
                        await HandleToteLoad(request);
                        break;
@@ -109,6 +161,13 @@
                    case EventType.robot_reach:
                        await HandleRobotReach(request);
                        break;
                    case EventType.task:
                        await HandleTaskStatusChange(request);
                        break;
                    case EventType.task_allocated:
                        await HandleTaskAllocated(request);
                        break;
                    default:
                        _logger.LogWarning("未知的事件类型: {EventType}", request.EventType);
                        break;
@@ -156,6 +215,7 @@
            _logger.LogInformation("任务完成: TaskCode={TaskCode}, Container={Container}, Robot={Robot}",
                request.TaskCode, request.ContainerCode, request.RobotCode);
            _taskService.TaskCompleted(request.TaskCode);
            // æ ¹æ®ä¸åŒçš„任务类型进行特殊处理
            if (request.Weight.HasValue)
            {
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Inbound/InboundOrderController.cs
@@ -5,6 +5,7 @@
using SqlSugar;
using System.Net;
using System.Threading.Tasks;
using WIDESEA_BasicService;
using WIDESEA_Common.OrderEnum;
using WIDESEA_Core;
using WIDESEA_Core.Attributes;
@@ -30,16 +31,20 @@
        private readonly WIDESEA_IBasicService.IInvokeMESService _invokeMESService;
        private readonly IESSApiService _eSSApiService;
        public InboundOrderController(IInboundOrderService service, WIDESEA_IBasicService.IErpApiService erpApiService, WIDESEA_IBasicService.IInvokeMESService invokeMESService, IESSApiService eSSApiService) : base(service)
        private readonly IDailySequenceService _dailySequenceService;
        public InboundOrderController(IInboundOrderService service, WIDESEA_IBasicService.IErpApiService erpApiService, WIDESEA_IBasicService.IInvokeMESService invokeMESService, IESSApiService eSSApiService, IDailySequenceService dailySequenceService) : base(service)
        {
            this.erpApiService = erpApiService;
            _invokeMESService = invokeMESService;
            _eSSApiService = eSSApiService;
            _dailySequenceService = dailySequenceService;
        }
        [HttpPost, Route("Test"), AllowAnonymous, MethodParamsValidate]
        public async Task<WebResponseContent> Test()
        {
            await _dailySequenceService.GetNextSequenceAsync();
            //erpApiService.GetSuppliersAsync();
            //erpApiService.GetMaterialUnitAsync();
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_WMSServer/WIDESEA_WMSServer.csproj
@@ -53,6 +53,7 @@
    </ItemGroup>
    
    <ItemGroup>
      <ProjectReference Include="..\WIDESEA_AllocateService\WIDESEA_AllocateService.csproj" />
      <ProjectReference Include="..\WIDESEA_BasicService\WIDESEA_BasicService.csproj" />
      <ProjectReference Include="..\WIDESEA_CheckService\WIDESEA_CheckService.csproj" />
      <ProjectReference Include="..\WIDESEA_InboundService\WIDESEA_InboundService.csproj" />