Browse Source

Merge branch 'dev_DY_CC' of http://dev.ccwin-in.com:3000/BoXu.Zheng/WZC2 into dev_DY_CC

dev_DY_CC
郑勃旭 12 months ago
parent
commit
5e91b9817c
  1. 133
      be/DataExchange/Fawtyg/Win_in.Sfs.Wms.DataExchange.Fawtyg.MesAgent/Incoming/MesIncomingBackgroundWorker.cs
  2. 2
      be/DataExchange/Fawtyg/Win_in.Sfs.Wms.DataExchange.Fawtyg.TyrpAgent/TyrpAgentModule.cs
  3. 16
      be/DataExchange/Fawtyg/Win_in.Sfs.Wms.DataExchange.Fawtyg.TyrpAgent/appsettings.json
  4. 2
      be/Modules/BaseData/src/Win_in.Sfs.Basedata.Application.Contracts/ProductLineItems/IProductionLineItemAppService.cs
  5. 1
      be/Modules/BaseData/src/Win_in.Sfs.Basedata.Application.Contracts/ProductionLines/IProductionLineAppService.cs
  6. 35
      be/Modules/BaseData/src/Win_in.Sfs.Basedata.Application/ProductionLineItems/ProductionLineItemAppService.cs
  7. 10
      be/Modules/BaseData/src/Win_in.Sfs.Basedata.Application/ProductionLines/ProductionLineAppService.cs
  8. 1
      be/Modules/Inventory/src/Win_in.Sfs.Wms.Inventory.Application.Contracts/Balances/IBalanceAppService.cs
  9. 4
      be/Modules/Inventory/src/Win_in.Sfs.Wms.Inventory.Application.Contracts/Balances/Inputs/RecommendBalanceRequestInput.cs
  10. 46
      be/Modules/Inventory/src/Win_in.Sfs.Wms.Inventory.Application/Balances/BalanceAppService.cs
  11. 155
      be/Modules/Inventory/src/Win_in.Sfs.Wms.Inventory.Domain/Balances/BalanceManager.cs
  12. 39
      be/Modules/Inventory/src/Win_in.Sfs.Wms.Inventory.Domain/Balances/BalanceValidateExtension.cs
  13. 1
      be/Modules/Inventory/src/Win_in.Sfs.Wms.Inventory.Domain/Balances/IBalanceManager.cs
  14. 2
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Jobs/IssueJobs/AssembleIssueJobs/AssembleIssueJobAppService.cs
  15. 2
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Requests/DeliverRequests/DeliverRequestAppService.cs
  16. 212
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/Requests/DeliverRequestEventHandler.cs

133
be/DataExchange/Fawtyg/Win_in.Sfs.Wms.DataExchange.Fawtyg.MesAgent/Incoming/MesIncomingBackgroundWorker.cs

@ -45,72 +45,54 @@ public class MesIncomingBackgroundWorker : AsyncPeriodicBackgroundWorkerBase
return;
}
//Logger.LogInformation($"Read MesOut");//缴库
//var mesOutReader = workerContext.ServiceProvider.GetRequiredService<MesOutReader>();
//var mesOutConverter = workerContext.ServiceProvider.GetRequiredService<MesOutConverter>();
//var TransferNoteConverter = workerContext.ServiceProvider.GetRequiredService<QtyrfeConverter>();
////读取mes缴库
//var mesOutsFromExternalList = await mesOutReader.ReadAsync().ConfigureAwait(false);
//var mesOutsFromExternalList_ProductReceipt = mesOutsFromExternalList.Where(r => r.DataType == EnumIncomingDataType.ProductReceipt.ToString()).ToList();
//var mesOutsFromExternalList_TransferNote = mesOutsFromExternalList.Where(r => r.DataType == EnumIncomingDataType.TransferNote.ToString()).ToList();
////转换缴库数据(如果有质量补得数据直接生产移库数据移到客户库位)
//await mesOutConverter.ConvertAsync(mesOutsFromExternalList_ProductReceipt).ConfigureAwait(false);
//if (mesOutsFromExternalList_TransferNote.Count > 0)//如果有质量补则生产储位调拨任务
//{
// await TransferNoteConverter.ConvertAsync(mesOutsFromExternalList_TransferNote).ConfigureAwait(false);
//}
//上海和安徽无此接口
//Logger.LogInformation($"Read PullTask");//拉动任务
//var pullTaskReader = workerContext.ServiceProvider.GetRequiredService<PullTaskReader>();
//var pullTaskConverter = workerContext.ServiceProvider.GetRequiredService<PullTaskConverter>();
////读取并保存PullTask
//var pullTaskFromExternalList = await pullTaskReader.ReadAsync().ConfigureAwait(false);
////转换PullTask
//await pullTaskConverter.ConvertAsync(pullTaskFromExternalList).ConfigureAwait(false);
//Logger.LogInformation($"Read Scrap");//报废
//var scrapReader = workerContext.ServiceProvider.GetRequiredService<ScrapReader>();
//var scrapConverter = workerContext.ServiceProvider.GetRequiredService<ScrapConverter>();
////读取并保存Scrap
//var scrapsFromExternalList = await scrapReader.ReadAsync().ConfigureAwait(false);
////转换Scrap
//await scrapConverter.ConvertAsync(scrapsFromExternalList).ConfigureAwait(false);
//上海和安徽无此接口
//Logger.LogInformation($"Read Issue");
//var pckHandleService = workerContext.ServiceProvider.GetRequiredService<IssueReader>();
//var pckConverter = workerContext.ServiceProvider.GetRequiredService<IssueConverter>();
////读取并保持Pck
//var pcksFromExternalList = await pckHandleService.ReadAsync().ConfigureAwait(false);
////转换Pck
//await pckConverter.ConvertAsync(pcksFromExternalList).ConfigureAwait(false);
//Logger.LogInformation($"Read BackFlush");//耗用单
//var BackFlushReader = workerContext.ServiceProvider.GetRequiredService<BackFluReader>();
//var BackFlushConverter = workerContext.ServiceProvider.GetRequiredService<BackFluConverter>();
////读取并保存BackFlush
//var backFlushsFromExternalList = await BackFlushReader.ReadAsync().ConfigureAwait(false);
////转换BackFlush
//await BackFlushConverter.ConvertAsync(backFlushsFromExternalList).ConfigureAwait(false);
//Logger.LogInformation($"Read TransferNote");//储位调拨
//var TransferNoteReader = workerContext.ServiceProvider.GetRequiredService<QtyrfeReader>();
//// var TransferNoteConverter = workerContext.ServiceProvider.GetRequiredService<QtyrfeConverter>();
////读取并保存TransferNote
//var transferNoteFromExternalList = await TransferNoteReader.ReadAsync().ConfigureAwait(false);
////转换TransferNote
//await TransferNoteConverter.ConvertAsync(transferNoteFromExternalList).ConfigureAwait(false);
Logger.LogInformation($"Read MesOut");//缴库
var mesOutReader = workerContext.ServiceProvider.GetRequiredService<MesOutReader>();
var mesOutConverter = workerContext.ServiceProvider.GetRequiredService<MesOutConverter>();
var TransferNoteConverter = workerContext.ServiceProvider.GetRequiredService<QtyrfeConverter>();
//读取mes缴库
var mesOutsFromExternalList = await mesOutReader.ReadAsync().ConfigureAwait(false);
var mesOutsFromExternalList_ProductReceipt = mesOutsFromExternalList.Where(r => r.DataType == EnumIncomingDataType.ProductReceipt.ToString()).ToList();
var mesOutsFromExternalList_TransferNote = mesOutsFromExternalList.Where(r => r.DataType == EnumIncomingDataType.TransferNote.ToString()).ToList();
//转换缴库数据(如果有质量补得数据直接生产移库数据移到客户库位)
await mesOutConverter.ConvertAsync(mesOutsFromExternalList_ProductReceipt).ConfigureAwait(false);
if (mesOutsFromExternalList_TransferNote.Count > 0)//如果有质量补则生产储位调拨任务
{
await TransferNoteConverter.ConvertAsync(mesOutsFromExternalList_TransferNote).ConfigureAwait(false);
}
//Logger.LogInformation($"Read Frozen");//冻结解冻
//var FrozenReader = workerContext.ServiceProvider.GetRequiredService<FrozenReader>();
//var FrozenConverter = workerContext.ServiceProvider.GetRequiredService<FrozenConverter>();
////读取并保存Frozen
//var mesNoteFromExternalList = await FrozenReader.ReadAsync().ConfigureAwait(false);
////转换Frozen
//await FrozenConverter.ConvertAsync(mesNoteFromExternalList).ConfigureAwait(false);
Logger.LogInformation($"Read Scrap");//报废
var scrapReader = workerContext.ServiceProvider.GetRequiredService<ScrapReader>();
var scrapConverter = workerContext.ServiceProvider.GetRequiredService<ScrapConverter>();
//读取并保存Scrap
var scrapsFromExternalList = await scrapReader.ReadAsync().ConfigureAwait(false);
//转换Scrap
await scrapConverter.ConvertAsync(scrapsFromExternalList).ConfigureAwait(false);
Logger.LogInformation($"Read BackFlush");//耗用单
var BackFlushReader = workerContext.ServiceProvider.GetRequiredService<BackFluReader>();
var BackFlushConverter = workerContext.ServiceProvider.GetRequiredService<BackFluConverter>();
//读取并保存BackFlush
var backFlushsFromExternalList = await BackFlushReader.ReadAsync().ConfigureAwait(false);
//转换BackFlush
await BackFlushConverter.ConvertAsync(backFlushsFromExternalList).ConfigureAwait(false);
Logger.LogInformation($"Read TransferNote");//储位调拨
var TransferNoteReader = workerContext.ServiceProvider.GetRequiredService<QtyrfeReader>();
// var TransferNoteConverter = workerContext.ServiceProvider.GetRequiredService<QtyrfeConverter>();
//读取并保存TransferNote
var transferNoteFromExternalList = await TransferNoteReader.ReadAsync().ConfigureAwait(false);
//转换TransferNote
await TransferNoteConverter.ConvertAsync(transferNoteFromExternalList).ConfigureAwait(false);
Logger.LogInformation($"Read Frozen");//冻结解冻
var FrozenReader = workerContext.ServiceProvider.GetRequiredService<FrozenReader>();
var FrozenConverter = workerContext.ServiceProvider.GetRequiredService<FrozenConverter>();
//读取并保存Frozen
var mesNoteFromExternalList = await FrozenReader.ReadAsync().ConfigureAwait(false);
//转换Frozen
await FrozenConverter.ConvertAsync(mesNoteFromExternalList).ConfigureAwait(false);
Logger.LogInformation($"Read Delivery");//成品发运
@ -130,7 +112,28 @@ public class MesIncomingBackgroundWorker : AsyncPeriodicBackgroundWorkerBase
var callMtlFromExternalList = await CallMtlReader.ReadAsync().ConfigureAwait(false);
//转换Delivery
await CallMtlConverter.ConvertAsync(callMtlFromExternalList).ConfigureAwait(false);
Logger.LogInformation($"Completed: Handling {Incoming}");
#region 未启用接口启用时需要看逻辑修改
//上海和安徽无此接口
//Logger.LogInformation($"Read PullTask");//拉动任务
//var pullTaskReader = workerContext.ServiceProvider.GetRequiredService<PullTaskReader>();
//var pullTaskConverter = workerContext.ServiceProvider.GetRequiredService<PullTaskConverter>();
////读取并保存PullTask
//var pullTaskFromExternalList = await pullTaskReader.ReadAsync().ConfigureAwait(false);
////转换PullTask
//await pullTaskConverter.ConvertAsync(pullTaskFromExternalList).ConfigureAwait(false);
//上海和安徽无此接口
//Logger.LogInformation($"Read Issue");
//var pckHandleService = workerContext.ServiceProvider.GetRequiredService<IssueReader>();
//var pckConverter = workerContext.ServiceProvider.GetRequiredService<IssueConverter>();
////读取并保持Pck
//var pcksFromExternalList = await pckHandleService.ReadAsync().ConfigureAwait(false);
////转换Pck
//await pckConverter.ConvertAsync(pcksFromExternalList).ConfigureAwait(false);
#endregion
}
}

2
be/DataExchange/Fawtyg/Win_in.Sfs.Wms.DataExchange.Fawtyg.TyrpAgent/TyrpAgentModule.cs

@ -172,7 +172,7 @@ public class TyrpAgentModule : AbpModule
ApplicationInitializationContext context)
{
context.AddBackgroundWorkerAsync<TyrpIncomingBackgroundWorker>();
// context.AddBackgroundWorkerAsync<TyrpIncomingBackgroundWorker>();
context.AddBackgroundWorkerAsync<TyrpOutgoingBackgroundWorker>();
}

16
be/DataExchange/Fawtyg/Win_in.Sfs.Wms.DataExchange.Fawtyg.TyrpAgent/appsettings.json

@ -1,13 +1,13 @@
{
"ConnectionStrings": {
"Default": "Server=10.164.113.32,1818\\SHDB;Database=Wms_Dy_ShangHai;uid=ShWmsUser;pwd=Faty@Wms_20230413#SH;TrustServerCertificate=True",
"DataExchange": "Server=10.164.113.32,1818\\SHDB;Database=Wms_DataExchange_Main_Dy_ShangHai;uid=ShWmsUser;pwd=Faty@Wms_20230413#SH;TrustServerCertificate=True",
"TYRP": "Server=10.164.113.32,1818\\SHDB;Database=TYRP;Uid=ShWmsUser;Pwd=Faty@Wms_20230413#SH;TrustServerCertificate=True",
"Default": "Server=dev.ccwin-in.com,13319;Database=WMS_DongYang_Main_CC;uid=ccwin-in;pwd=Microsoft@2022;TrustServerCertificate=True;Encrypt=false",
"DataExchange": "Server=dev.ccwin-in.com,13319;Database=WMS_DongYang_DataExchange_CC;uid=ccwin-in;pwd=Microsoft@2022;TrustServerCertificate=True;Encrypt=false",
"TYRP": "Server=dev.ccwin-in.com,13319;Database=TYRP_CC;Uid=ccwin-in;Pwd=Microsoft@2022;TrustServerCertificate=True",
"SYBASE_TYRP": "Data Source=10.164.115.137; Port=5000; Database=mesdb; Uid=sa; Pwd=dawning;Charset=cp850;" //iso_1
},
"AuthServer": {
"Authority": "http://10.164.113.31:60083/",
"Authority": "http://dev.ccwin-in.com:60083/",
"RequireHttpsMetadata": "false",
"SwaggerClientId": "admin",
"SwaggerClientSecret": "1q2w3E*",
@ -26,16 +26,16 @@
"RemoteServices": {
"BaseData": {
"BaseUrl": "http://10.164.113.31:60084/"
"BaseUrl": "http://dev.ccwin-in.com:60084/"
},
"Store": {
"BaseUrl": "http://10.164.113.31:60085/"
"BaseUrl": "http://dev.ccwin-in.com:60085/"
},
"Label": {
"BaseUrl": "http://10.164.113.31:60082/"
"BaseUrl": "http://dev.ccwin-in.com:60082/"
},
"Auth": {
"BaseUrl": "http://10.164.113.31:60083/"
"BaseUrl": "http://dev.ccwin-in.com:60083/"
}
},
"TyrpOptions": {

2
be/Modules/BaseData/src/Win_in.Sfs.Basedata.Application.Contracts/ProductLineItems/IProductionLineItemAppService.cs

@ -4,6 +4,7 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Win_in.Sfs.Shared.Application.Contracts;
using Win_in.Sfs.Shared.Domain.Shared;
namespace Win_in.Sfs.Basedata.Application.Contracts;
@ -16,4 +17,5 @@ public interface IProductionLineItemAppService
Task<ProductionLineItemDTO> GetByProductLineCodeAndItemCodeAsync(string productLineCode,
string itemCode);
Task<List<string>> GetByProductLineCodeAndItemCodeAndErpLocationCodeAsync(List<EnumLocationType> locationType, string erpLocationCodes, string itemCode);
}

1
be/Modules/BaseData/src/Win_in.Sfs.Basedata.Application.Contracts/ProductionLines/IProductionLineAppService.cs

@ -12,4 +12,5 @@ public interface IProductionLineAppService
{
Task<ProductionLineDTO> GetByLocationCodeAsync(string locationCode);
Task<List<ProductionLineDTO>> GetByLocationCodeAsync(EnumProductionLineType productionLineType);
Task<List<ProductionLineDTO>> GetByLocationCodesAsync(List<string> locationCode);
}

35
be/Modules/BaseData/src/Win_in.Sfs.Basedata.Application/ProductionLineItems/ProductionLineItemAppService.cs

@ -1,12 +1,18 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
using DocumentFormat.OpenXml.Office2016.Drawing.ChartDrawing;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp;
using Volo.Abp.Caching;
using Volo.Abp.ObjectMapping;
using Win_in.Sfs.Basedata.Application.Contracts;
using Win_in.Sfs.Basedata.Domain;
using Win_in.Sfs.Basedata.Domain.Shared;
using Win_in.Sfs.Shared.Domain.Shared;
namespace Win_in.Sfs.Basedata.Application;
@ -16,13 +22,17 @@ public class ProductionLineItemAppService :
SfsBaseDataAppServiceBase<ProductionLineItem, ProductionLineItemDTO, SfsBaseDataRequestInputBase,
ProductionLineItemEditInput, ProductionLineItemImportInput>, IProductionLineItemAppService
{
private readonly IProductionLineAppService _productionLineAppService ;
private readonly ILocationAppService _locationAppService ;
public ProductionLineItemAppService(
IProductionLineItemRepository repository, IDistributedCache<ProductionLineItemDTO> cache
IProductionLineItemRepository repository, IDistributedCache<ProductionLineItemDTO> cache, IProductionLineAppService productionLineAppService, ILocationAppService locationAppService
) : base(repository, cache)
{
base.CreatePolicyName = ProductionLineItemPermissions.Create;
base.UpdatePolicyName = ProductionLineItemPermissions.Update;
base.DeletePolicyName = ProductionLineItemPermissions.Delete;
_productionLineAppService = productionLineAppService;
_locationAppService = locationAppService;
}
[HttpPost("upsert")]
@ -56,4 +66,27 @@ public class ProductionLineItemAppService :
.FindAsync(p => p.ProdLineCode == productLineCode && p.ItemCode == itemCode).ConfigureAwait(false);
return ObjectMapper.Map<ProductionLineItem, ProductionLineItemDTO>(entityList);
}
[HttpPost("get-by-productlinecode-and-itemcode-and-erplocationcode-async")]
public virtual async Task<List<string>> GetByProductLineCodeAndItemCodeAndErpLocationCodeAsync(List<EnumLocationType> locationType, string erpLocationCodes,string itemCode)
{
List<string> list = new List<string>();
var locations= await _locationAppService.GetListByTypesAndErpCodeAsync(locationType, erpLocationCodes).ConfigureAwait(false);
if (locations.Count <= 0)
{
throw new UserFriendlyException($"未维护储位基础信息!");
}
else
{
var pls= await _productionLineAppService.GetByLocationCodesAsync(locations.Select(r=>r.Code).ToList()).ConfigureAwait(false);
var plscode = pls.Select(r => r.Code).ToList();
var entitys= await _repository.GetListAsync(r => r.ItemCode == itemCode && plscode.Contains(r.ProdLineCode)).ConfigureAwait(false);
foreach (var entity in entitys)
{
var locationcodes= JsonSerializer.Deserialize<List<string>>(entity.ProductLocationCodeListJson);
list.AddRange(locationcodes);
}
}
return list;
}
}

10
be/Modules/BaseData/src/Win_in.Sfs.Basedata.Application/ProductionLines/ProductionLineAppService.cs

@ -60,7 +60,17 @@ public class ProductionLineAppService
return ObjectMapper.Map<ProductionLine, ProductionLineDTO>(entity);
}
[HttpPost("get-by-locations")]
public virtual async Task<List<ProductionLineDTO>> GetByLocationCodesAsync(List<string> locationCode)
{
var entitys = await _repository.GetListAsync(p => locationCode.Contains(p.LocationCode) ).ConfigureAwait(false);
if (entitys == null)
{
throw new UserFriendlyException($"库位不存在");
}
return ObjectMapper.Map<List<ProductionLine>,List< ProductionLineDTO>>(entitys);
}
[HttpPost("get-by-type")]
public virtual async Task<List<ProductionLineDTO>> GetByLocationCodeAsync(EnumProductionLineType productionLineType)
{

1
be/Modules/Inventory/src/Win_in.Sfs.Wms.Inventory.Application.Contracts/Balances/IBalanceAppService.cs

@ -175,4 +175,5 @@ public interface IBalanceAppService
/// <returns></returns>
Task<BalanceDTO> GetRealQtyByPackingCodeAndItemCodeAndLocationCodeAndStatusAsync(string packingCode,
string itemCode, string locationCode, EnumInventoryStatus status,string lot);
Task<List<BalanceDTO>> GetRecommendBalancesByLocationsExpectOldBalancesAsync(RecommendBalanceRequestInput input);
}

4
be/Modules/Inventory/src/Win_in.Sfs.Wms.Inventory.Application.Contracts/Balances/Inputs/RecommendBalanceRequestInput.cs

@ -43,6 +43,10 @@ public class RecommendBalanceRequestInput
/// </summary>
[Display(Name = "是否必须有箱码")]
public bool IsPackingCode { get; set; } = false;
/// <summary>
/// 已经用过的库存
/// </summary>
public List<BalanceDTO> OldBalances { get; set; } = new ();
//public override string ToString()
//{

46
be/Modules/Inventory/src/Win_in.Sfs.Wms.Inventory.Application/Balances/BalanceAppService.cs

@ -10,6 +10,7 @@ using Microsoft.Extensions.Logging;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.ObjectMapping;
using Win_in.Sfs.Basedata.Application.Contracts;
using Win_in.Sfs.Shared.Application.Contracts;
using Win_in.Sfs.Shared.Domain;
@ -595,6 +596,51 @@ public class BalanceAppService
return dtos;
}
/// <summary>
/// 根据发料任务需求的库位,算出推荐的库存 (在获取时 已经去除了预占用和已经推荐过的库存)
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
[HttpGet("recommend-list-location-by-locations-expect-oldbalances")]
public virtual async Task<List<BalanceDTO>> GetRecommendBalancesByLocationsExpectOldBalancesAsync(RecommendBalanceRequestInput input)
{
var traceId = GuidGenerator.Create();
var itemCode = input.ItemCode;
var qty = input.Qty;
var locations = input.Locations;
var statuses = input.Statuses;
foreach (var location in locations)
{
var locationDto = await _locationAclService.GetByCodeAsync(location).ConfigureAwait(false);
if (locationDto != null)
{
if (input.LocationAreas == null)
{
input.LocationAreas = new List<string>();
}
input.LocationAreas.Add(locationDto.AreaCode);
if (input.LocationTypes == null)
{
input.LocationTypes = new List<EnumLocationType>();
}
input.LocationTypes.Add(locationDto.Type);
}
}
Logger.LogDebug(traceId + "|Input:" + input);
var oldBalances = ObjectMapper.Map<List<BalanceDTO>, List<Balance>>(input.OldBalances);
var balances = await _balanceManager
.GetRecommendBalancesByLocationExpectOldBalancesAsync(traceId, itemCode, qty, locations, statuses, input.IsPackingCode, oldBalances)
.ConfigureAwait(false);
var dtos = ObjectMapper.Map<List<Balance>, List<BalanceDTO>>(balances);
return dtos;
}
/// <summary>
/// 获取可用库存列表
/// </summary>

155
be/Modules/Inventory/src/Win_in.Sfs.Wms.Inventory.Domain/Balances/BalanceManager.cs

@ -615,7 +615,162 @@ public class BalanceManager : DomainService, IBalanceManager
#endregion
}
/// <summary>
/// 根据库位获取推荐库位
/// </summary>
/// <param name="traceId"></param>
/// <param name="itemCode"></param>
/// <param name="requestQty"></param>
/// <param name="validLocations"></param>
/// <param name="validStatuses"></param>
/// <returns></returns>
/// <exception cref="UserFriendlyException"></exception>
public virtual async Task<List<Balance>> GetRecommendBalancesByLocationExpectOldBalancesAsync(Guid traceId, string itemCode,
decimal requestQty, List<string> validLocations,
List<EnumInventoryStatus> validStatuses, bool ispackingcode,List<Balance> oldBalances)
{
var recommendBalances = new List<Balance>();//返回可使用的推荐库存余额
var item = await _itemBasicAclService.GetByCodeAsync(itemCode).ConfigureAwait(false);
if (item == null) //物品是否存在
{
// throw new UserFriendlyException($"未找到代码为 {itemCode} 的物料记录");
return recommendBalances;
}
//构造查询条件
Expression<Func<Balance, bool>> expression = p => p.ItemCode == itemCode;
expression = expression.And(p => validStatuses.Contains(p.Status));
expression = expression.And(p => p.IsActive);
//如果物品的有效期不是无限的, 要过滤掉过期库存
if (item.ValidityUnit != EnumValidityUnit.Infinite)
{
expression = expression.And(p => p.ExpireDate > DateTime.Now);
}
//排除无箱码库存
if (ispackingcode)
{
expression = expression.And(p => !string.IsNullOrEmpty(p.PackingCode));
}
//筛选有效库区 2023-6-29 李智慧 王旭 袁静雯 确认不需要做区域校验
//if (validLocationAreas.Any())
//{
// if (!string.IsNullOrEmpty(validLocationAreas[0]))
// {
// expression = expression.And(p => validLocationAreas.Contains(p.LocationArea));
// }
//}
var allBalances = await
(await _balanceRepository.GetDbSetAsync().ConfigureAwait(false))
.Where(expression)
.AsNoTracking()
.ToListAsync().ConfigureAwait(false);
var balanceLocationCodes = allBalances.Select(p => p.LocationCode).Distinct().ToList();
var locations = await _locationAclService.GetByCodesAsync(balanceLocationCodes).ConfigureAwait(false);
//筛选有效库位类型
if (validLocations.Any())
{
locations = locations.Where(p => validLocations.Contains(p.Code)).ToList();
}
var locationCodes = locations.Where(p => p.EnablePick).Select(p => p.Code).ToList();
Logger.LogDebug(traceId + "|Locations:" + locationCodes.JoinAsString(","));
if (!locationCodes.Any())
{
return recommendBalances;
}
//获取物品存储关系
var itemStoreRelationDict = await GetItemStoreRelationDictAsync(itemCode, locationCodes).ConfigureAwait(false);
//过滤掉无用的库位代码
locationCodes = itemStoreRelationDict.Keys.ToList();
locations = locations.Where(p => locationCodes.Contains(p.Code)).ToList();
Logger.LogDebug(traceId + "|LocationsInStoreRelation:" + locationCodes.JoinAsString(","));
var usableBalances = allBalances.Where(p => locationCodes.Contains(p.LocationCode)).ToList();
LogDebug(traceId, usableBalances, "Balances");
if (!usableBalances.Any())
{
return recommendBalances;
}
//读取该itemCode的预占用库存
var expectOuts = await
(await _expectOutRepository.GetDbSetAsync().ConfigureAwait(false))
.AsNoTracking()
.Where(p => p.ItemCode == itemCode
&& locationCodes.Contains(p.LocationCode)
&& validStatuses.Contains(p.Status))
.ToListAsync().ConfigureAwait(false);
LogDebug(traceId, expectOuts, "ExpectOut");
var containerCodes = usableBalances
.Where(p => !string.IsNullOrEmpty(p.ContainerCode))
.Select(p => p.ContainerCode)
.ToList();
var expectOutContainerCodes = await
(await _expectOutRepository.GetDbSetAsync().ConfigureAwait(false))
.Where(p => containerCodes.Contains(p.ContainerCode))
.GroupBy(p => p.ContainerCode)
.Select(d => d.Key)
.ToListAsync().ConfigureAwait(false);
usableBalances
//扣减已占用库存
.DecreaseExpectOutQty(expectOuts, oldBalances, locations)
//去除不可拆箱 拆托的且有预占用的库存余额
.IgnoreExpectOutOfSameContainer(expectOutContainerCodes, itemStoreRelationDict, locations)
//过滤掉不允许拣料的库位
.FilterLocationEnablePickAsync(locations)
//排序库存余额 最终可用的余额集合
.SortByFifo();
LogDebug(traceId, usableBalances, "AvailableBalances");
var usableBalanceQueue = new Queue<Balance>(usableBalances);
var remainQty = requestQty;
while (usableBalanceQueue.TryDequeue(out var usableBalance))
{
if (usableBalance.Qty <= 0)
{
continue;
}
var location = locations.First(p => p.Code == usableBalance.LocationCode);
var itemStoreRelation = itemStoreRelationDict[usableBalance.LocationCode];
var recommendBalance = new Balance(usableBalance);
var recommendQty =
GetRecommendQty(traceId, requestQty, remainQty, usableBalance, location, itemStoreRelation);
recommendBalance.Qty = recommendQty;
recommendBalances.Add(recommendBalance);
remainQty -= recommendQty;
//如果剩余数量小于等于零, 说明所有请求数量已满足, 退出循环
if (remainQty <= 0)
{
break;
}
}
return recommendBalances;
#region Old
// var availableQty = GetAvailableQty(traceId, requestQty, 0, usableBalances, itemStoreRelationDict, locations, recommendBalances);
//
// if (availableQty >= requestQty)
// {
// return recommendBalances;
// }
// var availableBalanceQty = usableBalances.Sum(p => p.Qty);
// throw new UserFriendlyException($"物料 {itemCode} 的可用库存余额 {availableBalanceQty} 不足");
#endregion
}
/// <summary>
/// 获取推荐库位
/// </summary>

39
be/Modules/Inventory/src/Win_in.Sfs.Wms.Inventory.Domain/Balances/BalanceValidateExtension.cs

@ -56,7 +56,46 @@ public static class BalanceValidateExtension
return balances;
}
/// <summary>
/// 扣除预计出库存
/// </summary>
/// <param name="balances"></param>
/// <param name="expectOuts"></param>
/// <param name="locations"></param>
/// <returns></returns>
public static List<Balance> DecreaseExpectOutQty(this List<Balance> balances,
List<ExpectOut> expectOuts,List<Balance> oldBalances, List<LocationDTO> locations)
{
foreach (var balance in balances)
{
var location = locations.First(p => p.Code == balance.LocationCode);
var expectOutsOfBalance = expectOuts.Where(p =>
p.PackingCode == balance.PackingCode
&& p.ItemCode == balance.ItemCode
&& p.Lot == balance.Lot
&& p.LocationCode == balance.LocationCode
&& p.Status == balance.Status);
var expectOutsOfOldBalance = oldBalances.Where(p =>
p.PackingCode == balance.PackingCode
&& p.ItemCode == balance.ItemCode
&& p.Lot == balance.Lot
&& p.LocationCode == balance.LocationCode
&& p.Status == balance.Status);
var expectOutSumQty = !location.EnableSplitBox
? balance.Qty
: expectOutsOfBalance.Sum(p => p.Qty);
var expectOutOldSumQty = !location.EnableSplitBox
? balance.Qty
: expectOutsOfOldBalance.Sum(p => p.Qty);
balance.DecreaseQty(expectOutSumQty+ expectOutOldSumQty);
}
return balances;
}
/// <summary>
/// 忽略不可拆托,同一托盘的库存
/// </summary>

1
be/Modules/Inventory/src/Win_in.Sfs.Wms.Inventory.Domain/Balances/IBalanceManager.cs

@ -51,4 +51,5 @@ public interface IBalanceManager : IDomainService
Task<List<Balance>> GetUsableListAsync(string itemCode,
List<string> validLocations,
List<EnumInventoryStatus> validStatuses, bool isRemovePackingCode);
Task<List<Balance>> GetRecommendBalancesByLocationExpectOldBalancesAsync(Guid traceId, string itemCode, decimal requestQty, List<string> validLocations, List<EnumInventoryStatus> validStatuses, bool ispackingcode, List<Balance> oldBalances);
}

2
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Jobs/IssueJobs/AssembleIssueJobs/AssembleIssueJobAppService.cs

@ -217,7 +217,7 @@ public class AssembleIssueJobAppService
await _repository.UpdateAsync(assembleIssueJob).ConfigureAwait(false);
}
[HttpPost("CompleteAsync/{id}")]
[HttpPost("Complete/{id}")]
public async Task CompleteAsync(Guid id)
{
var assembleIssueJob = await _repository.FindAsync(id).ConfigureAwait(false);

2
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Requests/DeliverRequests/DeliverRequestAppService.cs

@ -56,7 +56,7 @@ public class DeliverRequestAppService :
public virtual async Task<List<DeliverRequestDTO>> HandleListAsync(List<Guid> ids)
{
var entitys = await _repository.GetListAsync(r=> ids.Contains(r.Id)).ConfigureAwait(false);
var entitys = await _repository.GetListAsync(r=> ids.Contains(r.Id),true).ConfigureAwait(false);
if (entitys.Select(r => r.CustomerCode).Distinct().Count()>1)
{
throw new UserFriendlyException($"所选申请涉及多个客户不能创建为一个发货单,请重新选择!");

212
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/Requests/DeliverRequestEventHandler.cs

@ -31,10 +31,11 @@ public class DeliverRequestEventHandler
private readonly IDeliverRequestManager _deliverRequestManager;
private readonly IBalanceAppService _balanceAppService;
private readonly ILocationAppService _locationAppService;
private readonly IProductionLineItemAppService _productionLineItemAppService;
public DeliverRequestEventHandler(
IDeliverJobAppService deliverJobApp
, IDeliverNoteAppService deliverNoteApp
, ICustomerAddressAppService customerAddressApp, IDeliverRequestManager deliverRequestManager, IBalanceAppService balanceAppService, ILocationAppService locationAppService)
, ICustomerAddressAppService customerAddressApp, IDeliverRequestManager deliverRequestManager, IBalanceAppService balanceAppService, ILocationAppService locationAppService, IProductionLineItemAppService productionLineItemAppService)
{
_deliverNoteApp = deliverNoteApp;
_deliverJobApp = deliverJobApp;
@ -42,6 +43,7 @@ public class DeliverRequestEventHandler
_deliverRequestManager = deliverRequestManager;
_balanceAppService = balanceAppService;
_locationAppService = locationAppService;
_productionLineItemAppService = productionLineItemAppService;
}
@ -98,11 +100,11 @@ public class DeliverRequestEventHandler
var noteCreateInput = await BuildDeliverNoteAsync(entity).ConfigureAwait(false);
await _deliverNoteApp.CreateAsync(noteCreateInput).ConfigureAwait(false);
}
else
{
var deliverJobCreateInputs = await BuildDeliverJobsAsync(entity).ConfigureAwait(false);
await _deliverJobApp.CreateManyAsync(deliverJobCreateInputs).ConfigureAwait(false);
}
//else
//{
// var deliverJobCreateInputs = await BuildDeliverJobsAsync(entity).ConfigureAwait(false);
// await _deliverJobApp.CreateManyAsync(deliverJobCreateInputs).ConfigureAwait(false);
//}
}
/// <summary>
/// 执行后
@ -156,7 +158,7 @@ public class DeliverRequestEventHandler
}
createInput.Details = new List<DeliverNoteDetailInput>();
List<BalanceDTO> oldBalances = new List<BalanceDTO>();
foreach (var detail in requests.SelectMany(r=>r.Details))
{
var locations = await _locationAppService.GetListByTypesAndErpCodeAsync(transactionType.OutLocationTypes, detail.AreaCode).ConfigureAwait(false);
@ -165,13 +167,14 @@ public class DeliverRequestEventHandler
throw new UserFriendlyException($"储位 {detail.AreaCode} 未找到对应的成品库和半成品库。");
}
var balances = await _balanceAppService.GetRecommendBalancesByLocationsAsync(
var balances = await _balanceAppService.GetRecommendBalancesByLocationsExpectOldBalancesAsync(
new RecommendBalanceRequestInput
{
ItemCode = detail.ItemCode,
Qty = detail.Qty,
Locations = locations.Select(r => r.Code).ToList(),
Statuses = transactionType.OutInventoryStatuses
Statuses = transactionType.OutInventoryStatuses,
OldBalances=oldBalances,
}).ConfigureAwait(false);
var sumQty = balances.Sum(t => t.Qty);
@ -180,7 +183,7 @@ public class DeliverRequestEventHandler
{
throw new UserFriendlyException($"物料号 {detail.ItemCode} 库存余额 {sumQty} 小于 {detail.Qty}。");
}
oldBalances.AddRange(balances);
foreach (var balance in balances)
{
var inputDetail = ObjectMapper.Map<BalanceDTO, DeliverNoteDetailInput>(balance);
@ -241,7 +244,7 @@ public class DeliverRequestEventHandler
}
createInput.Details = new List<DeliverNoteDetailInput>();
List<BalanceDTO> oldBalances = new List<BalanceDTO>();
foreach (var detail in request.Details)
{
var locations = await _locationAppService.GetListByTypesAndErpCodeAsync(transactionType.OutLocationTypes, detail.AreaCode).ConfigureAwait(false);
@ -250,13 +253,14 @@ public class DeliverRequestEventHandler
throw new UserFriendlyException($"储位 {detail.AreaCode} 未找到对应的成品库和半成品库。");
}
var balances = await _balanceAppService.GetRecommendBalancesByLocationsAsync(
var balances = await _balanceAppService.GetRecommendBalancesByLocationsExpectOldBalancesAsync(
new RecommendBalanceRequestInput
{
ItemCode = detail.ItemCode,
Qty = detail.Qty,
Locations = locations.Select(r=>r.Code).ToList(),
Statuses = transactionType.OutInventoryStatuses
Statuses = transactionType.OutInventoryStatuses,
OldBalances=oldBalances,
}).ConfigureAwait(false);
var sumQty = balances.Sum(t => t.Qty);
@ -265,7 +269,7 @@ public class DeliverRequestEventHandler
{
throw new UserFriendlyException($"物料号 {detail.ItemCode} 库存余额 {sumQty} 小于 {detail.Qty}。");
}
oldBalances.AddRange(balances);
foreach (var balance in balances)
{
var inputDetail = ObjectMapper.Map<BalanceDTO, DeliverNoteDetailInput>(balance);
@ -295,96 +299,96 @@ public class DeliverRequestEventHandler
return createInput;
}
private async Task<List<DeliverJobEditInput>> BuildDeliverJobsAsync(DeliverRequest request)
{
var transSubType = EnumTransSubType.None;
switch (request.DeliverRequestType)
{
case EnumDeliverRequestType.Normal:
transSubType = EnumTransSubType.Deliver_Standard;
break;
case EnumDeliverRequestType.FIS:
transSubType = EnumTransSubType.Deliver_FIS;
break;
case EnumDeliverRequestType.RAW:
transSubType = EnumTransSubType.Deliver_RAW;
break;
case EnumDeliverRequestType.None:
default:
throw new ArgumentOutOfRangeException();
}
var transactionType = await TransactionTypeAclService.GetByTransTypeAsync(EnumTransType.Deliver, transSubType)
.ConfigureAwait(false);
var createInput = ObjectMapper.Map<DeliverRequest, DeliverJobEditInput>(request);
var customerAddress =
(await _customerAddressApp.GetByCustomerCodeAsync(request.CustomerCode).ConfigureAwait(false))
.FirstOrDefault();
LocationDTO toLocation = null;
if (customerAddress != null && !string.IsNullOrEmpty(customerAddress.LocationCode))
{
toLocation = await LocationAclService.GetByCodeAsync(customerAddress.LocationCode).ConfigureAwait(false);
Check.NotNull(toLocation, $"客户库位 {customerAddress.LocationCode} 不存在");
}
createInput.Details = new List<DeliverJobDetailInput>();
foreach (var detail in request.Details)
{
var balances = await BalanceAclService.GetRecommendBalancesAsync(
new RecommendBalanceRequestInput
{
ItemCode = detail.ItemCode,
Qty = detail.Qty,
LocationTypes = transactionType.OutLocationTypes,
LocationAreas = new List<string> { detail.AreaCode },
Statuses = transactionType.OutInventoryStatuses
}).ConfigureAwait(false);
var sumQty = balances.Sum(t => t.Qty);
if (sumQty < detail.Qty)
{
throw new UserFriendlyException($"物料号 {detail.ItemCode} 库存余额 {sumQty} 小于 {detail.Qty}。");
}
foreach (var balance in balances)
{
var inputDetail = ObjectMapper.Map<BalanceDTO, DeliverJobDetailInput>(balance);
if (toLocation != null)
{
inputDetail.ToLocationCode = toLocation.Code;
inputDetail.ToLocationErpCode = toLocation.ErpLocationCode;
inputDetail.ToWarehouseCode = toLocation.WarehouseCode;
}
var item = await ItemBasicAclService.GetByCodeAsync(balance.ItemCode).ConfigureAwait(false);
if (item != null)
{
inputDetail.StdPackQty = item.StdPackQty;
}
createInput.Details.Add(inputDetail);
}
var firstBalance = balances.FirstOrDefault();
var location = await LocationAclService.GetByCodeAsync(firstBalance.LocationCode).ConfigureAwait(false);
if (location != null)
{
createInput.WarehouseCode = location.WarehouseCode;
createInput.WorkGroupCode = location.WorkGroupCode;
}
}
createInput.Priority = PriorityHelper.GetPriority(Clock);
createInput.PriorityIncrement = 1;
return new List<DeliverJobEditInput> { createInput };
}
//private async Task<List<DeliverJobEditInput>> BuildDeliverJobsAsync(DeliverRequest request)
//{
// var transSubType = EnumTransSubType.None;
// switch (request.DeliverRequestType)
// {
// case EnumDeliverRequestType.Normal:
// transSubType = EnumTransSubType.Deliver_Standard;
// break;
// case EnumDeliverRequestType.FIS:
// transSubType = EnumTransSubType.Deliver_FIS;
// break;
// case EnumDeliverRequestType.RAW:
// transSubType = EnumTransSubType.Deliver_RAW;
// break;
// case EnumDeliverRequestType.None:
// default:
// throw new ArgumentOutOfRangeException();
// }
// var transactionType = await TransactionTypeAclService.GetByTransTypeAsync(EnumTransType.Deliver, transSubType)
// .ConfigureAwait(false);
// var createInput = ObjectMapper.Map<DeliverRequest, DeliverJobEditInput>(request);
// var customerAddress =
// (await _customerAddressApp.GetByCustomerCodeAsync(request.CustomerCode).ConfigureAwait(false))
// .FirstOrDefault();
// LocationDTO toLocation = null;
// if (customerAddress != null && !string.IsNullOrEmpty(customerAddress.LocationCode))
// {
// toLocation = await LocationAclService.GetByCodeAsync(customerAddress.LocationCode).ConfigureAwait(false);
// Check.NotNull(toLocation, $"客户库位 {customerAddress.LocationCode} 不存在");
// }
// createInput.Details = new List<DeliverJobDetailInput>();
// foreach (var detail in request.Details)
// {
// var balances = await BalanceAclService.GetRecommendBalancesAsync(
// new RecommendBalanceRequestInput
// {
// ItemCode = detail.ItemCode,
// Qty = detail.Qty,
// LocationTypes = transactionType.OutLocationTypes,
// LocationAreas = new List<string> { detail.AreaCode },
// Statuses = transactionType.OutInventoryStatuses
// }).ConfigureAwait(false);
// var sumQty = balances.Sum(t => t.Qty);
// if (sumQty < detail.Qty)
// {
// throw new UserFriendlyException($"物料号 {detail.ItemCode} 库存余额 {sumQty} 小于 {detail.Qty}。");
// }
// foreach (var balance in balances)
// {
// var inputDetail = ObjectMapper.Map<BalanceDTO, DeliverJobDetailInput>(balance);
// if (toLocation != null)
// {
// inputDetail.ToLocationCode = toLocation.Code;
// inputDetail.ToLocationErpCode = toLocation.ErpLocationCode;
// inputDetail.ToWarehouseCode = toLocation.WarehouseCode;
// }
// var item = await ItemBasicAclService.GetByCodeAsync(balance.ItemCode).ConfigureAwait(false);
// if (item != null)
// {
// inputDetail.StdPackQty = item.StdPackQty;
// }
// createInput.Details.Add(inputDetail);
// }
// var firstBalance = balances.FirstOrDefault();
// var location = await LocationAclService.GetByCodeAsync(firstBalance.LocationCode).ConfigureAwait(false);
// if (location != null)
// {
// createInput.WarehouseCode = location.WarehouseCode;
// createInput.WorkGroupCode = location.WorkGroupCode;
// }
// }
// createInput.Priority = PriorityHelper.GetPriority(Clock);
// createInput.PriorityIncrement = 1;
// return new List<DeliverJobEditInput> { createInput };
//}
#endregion
}

Loading…
Cancel
Save