Browse Source

装配叫料功能更新

dev_DY_CC
周红军 12 months ago
parent
commit
ff13a8e1fc
  1. 8
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/AssembleIssueJobs/AssembleIssueJobPermissions.cs
  2. 2
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/AssembleIssueJobs/DTOs/AssembleIssueJobDTO.cs
  3. 10
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/AssembleIssueJobs/IAssembleIssueJobAppService.cs
  4. 3
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/AssembleIssueJobs/Inputs/AssembleIssueJobEditInput.cs
  5. 15
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/AssembleIssueNotes/AssembleIssueNotePermissions.cs
  6. 1
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/AssembleIssueNotes/DTOs/AssembleIssueNoteDTO.cs
  7. 1
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/AssembleIssueNotes/IAssembleIssueNoteAppService.cs
  8. 4
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/AssembleIssueNotes/Inputs/AssembleIssueNoteEditInput.cs
  9. 2
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/AssembleIssueNotes/Inputs/AssembleIssueNoteImportInput.cs
  10. 8
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/KittingIssueNotes/KittingIssueNotePermissions.cs
  11. 10
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/IssueRequest/AssembleIssueRequests/AssembleIssueRequestPermissions.cs
  12. 4
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/IssueRequest/AssembleIssueRequests/DTOs/AssembleIssueRequestDTO.cs
  13. 71
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/IssueRequest/AssembleIssueRequests/DTOs/AssembleIssueRequestDetailDTO.cs
  14. 2
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/IssueRequest/AssembleIssueRequests/IAssembleIssueRequestAppService.cs
  15. 7
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/IssueRequest/AssembleIssueRequests/Inputs/AssembleIssueRequestEditInput.cs
  16. 12
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/IssueRequest/AssembleIssueRequests/Inputs/AssembleIssueRequestImportInput.cs
  17. 479
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Jobs/IssueJobs/AssembleIssueJobs/AssembleIssueJobAppService.cs
  18. 21
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Notes/IssueNotes/AssembleIssueNotes/AssembleIssueNoteAppService.cs
  19. 250
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Requests/IssuelRequests/AssembleIssueRequests/AssembleIssueRequestAppService.cs
  20. 3
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/IssueJobs/AssembleIssueJobs/AssembleIssueJob.cs
  21. 2
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/IssueJobs/AssembleIssueJobs/AssembleIssueJobDetail.cs
  22. 5
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/IssueJobs/AssembleIssueJobs/AssembleIssueJobManager.cs
  23. 8
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Notes/IssueNotes/AssembleIssueNotes/AssembleIssueNote.cs
  24. 9
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/IssueRequests/AssembleIssueRequests/AssembleIssueRequest.cs
  25. 2
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/IssueRequests/AssembleIssueRequests/AssembleIssueRequestDetail.cs
  26. 34
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/IssueRequests/AssembleIssueRequests/AssembleIssueRequestManager.cs
  27. 4
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Requests/IssueRequests/AssembleIssueRequests/AssembleIssueRequestDbContextModelCreatingExtensions.cs
  28. 9
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/AutoMapperProfiles/Jobs/AssembleJobAutoMapperProfile.cs
  29. 1
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/AutoMapperProfiles/Notes/AssembleNoteAutoMapperProfile.cs
  30. 39
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/AutoMapperProfiles/Requests/AssembleIssueRequestAutoMapperProfile.cs
  31. 146
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/Jobs/AssembleIssueJobEventHandler.cs
  32. 692
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/Requests/AssembleIssueRequestEventHandler.cs

8
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/AssembleIssueJobs/AssembleIssueJobPermissions.cs

@ -16,10 +16,10 @@ public static class AssembleIssueJobPermissions
public static void AddAssembleIssueJobPermission(this PermissionGroupDefinition permissionGroup)
{
var AssembleIssueJobPermission = permissionGroup.AddPermission(Default, StorePermissionDefinitionProvider.L(nameof(AssembleIssueJob)));
AssembleIssueJobPermission.AddChild(Create, StorePermissionDefinitionProvider.L(StorePermissions.CreateStr));
AssembleIssueJobPermission.AddChild(Update, StorePermissionDefinitionProvider.L(StorePermissions.UpdateStr));
AssembleIssueJobPermission.AddChild(Delete, StorePermissionDefinitionProvider.L(StorePermissions.DeleteStr));
var assembleIssueJobPermission = permissionGroup.AddPermission(Default, StorePermissionDefinitionProvider.L(nameof(AssembleIssueJob)));
assembleIssueJobPermission.AddChild(Create, StorePermissionDefinitionProvider.L(StorePermissions.CreateStr));
assembleIssueJobPermission.AddChild(Update, StorePermissionDefinitionProvider.L(StorePermissions.UpdateStr));
assembleIssueJobPermission.AddChild(Delete, StorePermissionDefinitionProvider.L(StorePermissions.DeleteStr));
permissionGroup.AddPermission(AutoAssembleIssueJob, StorePermissionDefinitionProvider.L(nameof(AutoAssembleIssueJob)));

2
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/AssembleIssueJobs/DTOs/AssembleIssueJobDTO.cs

@ -36,4 +36,6 @@ public class AssembleIssueJobDTO : SfsJobDTOBase<AssembleIssueJobDetailDTO>
[Display(Name = "使用在途库")]
public bool UseOnTheWayLocation { get; set; }
public EnumIssueSendType EnumIssueSendType { get; set; }
}

10
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/AssembleIssueJobs/IAssembleIssueJobAppService.cs

@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
@ -8,8 +9,15 @@ namespace Win_in.Sfs.Wms.Store.Application.Contracts;
public interface IAssembleIssueJobAppService
: ISfsJobAppServiceBase<AssembleIssueJobDTO, SfsJobRequestInputBase, AssembleIssueJobCheckInput, AssembleIssueJobEditInput>
{
Task CancelByMaterialRequestAsync(string assembleNumber);
Task CancelByMaterialRequestAsync(string requestNumber);
Task<List<AssembleIssueJobDTO>> GetByRequestNumberAsync(string requestNumber);
/// <summary>
/// 执行任务明细
/// </summary>
/// <returns></returns>
Task ExecuteDetailAsync(Guid masterId, Guid detailId, AssembleIssueJobDetailDTO issueJobDetailDto);
Task CompleteAsync(Guid id);
}

3
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/AssembleIssueJobs/Inputs/AssembleIssueJobEditInput.cs

@ -58,12 +58,13 @@ public class AssembleIssueJobEditInput : SfsJobCreateUpdateInputBase, ISfsJobCre
[Display(Name = "任务明细")]
[Required(ErrorMessage = "{0}是必填项")]
public List<AssembleIssueJobDetailInput> Details { get; set; } = new();
/// <summary>
/// 使用在途库
/// </summary>
[Display(Name = "使用在途库")]
public bool UseOnTheWayLocation { get; set; }
public EnumIssueSendType EnumIssueSendType { get; set; }
#endregion
}

15
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/AssembleIssueNotes/AssembleIssueNotePermissions.cs

@ -5,26 +5,19 @@ namespace Win_in.Sfs.Wms.Store.Application.Contracts;
public static class AssembleIssueNotePermissions
{
public const string Default = StorePermissions.GroupName + "." + nameof(AssembleIssueNote);
public const string Create = Default + "." + StorePermissions.CreateStr;
public const string Update = Default + "." + StorePermissions.UpdateStr;
public const string Delete = Default + "." + StorePermissions.DeleteStr;
//自动发料记录
public const string AutoAssembleIssueNote = StorePermissions.GroupName + "." + nameof(AutoAssembleIssueNote);
//直接发料
public const string DirectAssembleIssueNote = StorePermissions.GroupName + "." + nameof(DirectAssembleIssueNote);
public static void AddAssembleIssueNotePermission(this PermissionGroupDefinition permissionGroup)
{
var AssembleIssueNotePermission = permissionGroup.AddPermission(Default, StorePermissionDefinitionProvider.L(nameof(AssembleIssueNote)));
AssembleIssueNotePermission.AddChild(Create, StorePermissionDefinitionProvider.L(StorePermissions.CreateStr));
AssembleIssueNotePermission.AddChild(Update, StorePermissionDefinitionProvider.L(StorePermissions.UpdateStr));
AssembleIssueNotePermission.AddChild(Delete, StorePermissionDefinitionProvider.L(StorePermissions.DeleteStr));
var assembleIssueNotePermission = permissionGroup.AddPermission(Default, StorePermissionDefinitionProvider.L(nameof(AssembleIssueNote)));
assembleIssueNotePermission.AddChild(Create, StorePermissionDefinitionProvider.L(StorePermissions.CreateStr));
assembleIssueNotePermission.AddChild(Update, StorePermissionDefinitionProvider.L(StorePermissions.UpdateStr));
assembleIssueNotePermission.AddChild(Delete, StorePermissionDefinitionProvider.L(StorePermissions.DeleteStr));
permissionGroup.AddPermission(AutoAssembleIssueNote, StorePermissionDefinitionProvider.L(nameof(AutoAssembleIssueNote)));
permissionGroup.AddPermission(DirectAssembleIssueNote, StorePermissionDefinitionProvider.L(nameof(DirectAssembleIssueNote)));
}
}

1
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/AssembleIssueNotes/DTOs/AssembleIssueNoteDTO.cs

@ -44,4 +44,5 @@ public class AssembleIssueNoteDTO : SfsStoreDTOBase<AssembleIssueNoteDetailDTO>,
[Display(Name = "确认时间")]
public DateTime? ConfirmTime { get; set; }
public EnumIssueSendType EnumIssueSendType { get; set; }
}

1
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/AssembleIssueNotes/IAssembleIssueNoteAppService.cs

@ -12,5 +12,4 @@ public interface IAssembleIssueNoteAppService : ISfsStoreMasterReadOnlyAppServic
Task<AssembleIssueNoteDTO> ConfirmAsync(Guid id);
}

4
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/AssembleIssueNotes/Inputs/AssembleIssueNoteEditInput.cs

@ -27,7 +27,7 @@ public class AssembleIssueNoteEditInput : SfsStoreCreateOrUpdateInputBase
/// </summary>
[Display(Name = "任务ID")]
[Required(ErrorMessage = "{0}是必填项")]
public string JobNumber { get; set; }
public string JobNumber { get; set; }
/// <summary>
/// 明细列表
@ -52,5 +52,7 @@ public class AssembleIssueNoteEditInput : SfsStoreCreateOrUpdateInputBase
/// </summary>
[Display(Name = "使用在途库")]
public bool UseOnTheWayLocation { get; set; }
public EnumIssueSendType EnumIssueSendType { get; set; }
#endregion
}

2
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/AssembleIssueNotes/Inputs/AssembleIssueNoteImportInput.cs

@ -31,4 +31,6 @@ public class AssembleIssueNoteImportInput : SfsStoreImportInputBase, IHasJobNumb
[Display(Name = "使用在途库")]
[Required(ErrorMessage = "{0}是必填项")]
public bool UseOnTheWayLocation { get; set; }
public EnumIssueSendType EnumIssueSendType { get; set; }
}

8
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/KittingIssueNotes/KittingIssueNotePermissions.cs

@ -15,10 +15,10 @@ public static class KittingIssueNotePermissions
public static void AddKittingIssueNotePermission(this PermissionGroupDefinition permissionGroup)
{
var injectionNotePermission = permissionGroup.AddPermission(Default, StorePermissionDefinitionProvider.L(nameof(KittingIssueNote)));
injectionNotePermission.AddChild(Create, StorePermissionDefinitionProvider.L(StorePermissions.CreateStr));
injectionNotePermission.AddChild(Update, StorePermissionDefinitionProvider.L(StorePermissions.UpdateStr));
injectionNotePermission.AddChild(Delete, StorePermissionDefinitionProvider.L(StorePermissions.DeleteStr));
var kittingIssueNotePermission = permissionGroup.AddPermission(Default, StorePermissionDefinitionProvider.L(nameof(KittingIssueNote)));
kittingIssueNotePermission.AddChild(Create, StorePermissionDefinitionProvider.L(StorePermissions.CreateStr));
kittingIssueNotePermission.AddChild(Update, StorePermissionDefinitionProvider.L(StorePermissions.UpdateStr));
kittingIssueNotePermission.AddChild(Delete, StorePermissionDefinitionProvider.L(StorePermissions.DeleteStr));
}
}

10
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/IssueRequest/AssembleIssueRequests/AssembleIssueRequestPermissions.cs

@ -10,15 +10,13 @@ public static class AssembleIssueRequestPermissions
public const string Create = Default + "." + StorePermissions.CreateStr;
public const string Update = Default + "." + StorePermissions.UpdateStr;
public const string Delete = Default + "." + StorePermissions.DeleteStr;
public static void AddAssembleIssueRequestPermission(this PermissionGroupDefinition permissionGroup)
{
var AssembleIssueRequestPermission = permissionGroup.AddPermission(Default, StorePermissionDefinitionProvider.L(nameof(AssembleIssueRequest)));
AssembleIssueRequestPermission.AddChild(Create, StorePermissionDefinitionProvider.L(StorePermissions.CreateStr));
AssembleIssueRequestPermission.AddChild(Update, StorePermissionDefinitionProvider.L(StorePermissions.UpdateStr));
AssembleIssueRequestPermission.AddChild(Delete, StorePermissionDefinitionProvider.L(StorePermissions.DeleteStr));
var assembleIssueRequestPermission = permissionGroup.AddPermission(Default, StorePermissionDefinitionProvider.L(nameof(AssembleIssueRequest)));
assembleIssueRequestPermission.AddChild(Create, StorePermissionDefinitionProvider.L(StorePermissions.CreateStr));
assembleIssueRequestPermission.AddChild(Update, StorePermissionDefinitionProvider.L(StorePermissions.UpdateStr));
assembleIssueRequestPermission.AddChild(Delete, StorePermissionDefinitionProvider.L(StorePermissions.DeleteStr));
}
}

4
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/IssueRequest/AssembleIssueRequests/DTOs/AssembleIssueRequestDTO.cs

@ -1,4 +1,5 @@
using System.ComponentModel.DataAnnotations;
using Win_in.Sfs.Shared.Domain.Shared.Enums.Store;
namespace Win_in.Sfs.Wms.Store.Application.Contracts;
@ -8,8 +9,7 @@ public class AssembleIssueRequestDTO : SfsStoreRequestDTOBase<AssembleIssueReque
/// 叫料类型
/// </summary>
[Display(Name = "叫料类型")]
public string Type { get; set; }
public EnumIssueRequestType IssueRequestType { get; set; }
/// <summary>
/// 是否使用在途库
/// </summary>

71
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/IssueRequest/AssembleIssueRequests/DTOs/AssembleIssueRequestDetailDTO.cs

@ -8,49 +8,92 @@ namespace Win_in.Sfs.Wms.Store.Application.Contracts;
public class AssembleIssueRequestDetailDTO : SfsStoreDetailWithQtyDTOBase
{
#region 目标库位信息
/// <summary>
/// 目标库位
/// </summary>
[Display(Name = "目标库位")]
[StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
public string ToLocationCode { get; set; }
/// <summary>
/// 目标库区
/// </summary>
[Display(Name = "目标库区")]
public string ToLocationArea { get; set; }
/// <summary>
/// 已发数量
/// 目标库位组
/// </summary>
[Display(Name = "目标库位组")]
public string ToLocationGroup { get; set; }
/// <summary>
/// 目标ERP储位
/// </summary>
[Display(Name = "目标ERP储位")]
public string ToLocationErpCode { get; set; }
/// <summary>
/// 目标仓库
/// </summary>
[Display(Name = "目标仓库")]
public string ToWarehouseCode { get; set; }
#endregion
/// <summary>
/// 生产线
/// </summary>
public string ProdLine { get; set; }
/// <summary>
/// 已发数量
/// </summary>
[Display(Name = "已发数量")]
public decimal IssuedQty { get; set; }
/// <summary>
/// 已收数量
/// 已收数量
/// </summary>
[Display(Name = "已收数量")]
public decimal ReceivedQty { get; set; }
/// <summary>
/// 明细状态
/// 明细状态
/// </summary>
[Display(Name = "明细状态")]
public EnumStatus Status { get; set; }
/// <summary>
/// 请求未发
/// 请求未发 还未发送的数量
/// </summary>
[Display(Name = "请求未发")]
[NotMapped]
public decimal ToBeIssuedQty => Qty - IssuedQty;
/// <summary>
/// 已发未收
/// 已发未收
/// </summary>
[Display(Name = "已发未收")]
[NotMapped]
public decimal ToBeReceivedQty => IssuedQty - ReceivedQty;
/// <summary>
/// 请求未收
/// 请求未收
/// </summary>
[Display(Name = "请求未收")]
[NotMapped]
public decimal NotFinishQty => Qty - ReceivedQty;
/// <summary>
/// 需求箱数量
/// 位置码
/// </summary>
public string PositionCode { get; set; }
/// <summary>
/// 推荐类型
/// </summary>
public EnumRecommendType RecommendType { get; set; }
/// <summary>
/// 需求箱数量
/// </summary>
[Display(Name = "需求箱数量")]
public decimal BoxQty { get; set; }
}

2
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/IssueRequest/AssembleIssueRequests/IAssembleIssueRequestAppService.cs

@ -10,4 +10,6 @@ public interface IAssembleIssueRequestAppService
{
Task<AssembleIssueRequestDTO> CreateAndHandleAsync(AssembleIssueRequestEditInput input);
Task UpdateStatusCompletedAsync(string number);
Task<string> IsHasNewJobAsync(string requestNumber, List<string> jobNumber);
}

7
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/IssueRequest/AssembleIssueRequests/Inputs/AssembleIssueRequestEditInput.cs

@ -1,6 +1,7 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using Win_in.Sfs.Shared.Domain;
using Win_in.Sfs.Shared.Domain.Shared.Enums.Store;
namespace Win_in.Sfs.Wms.Store.Application.Contracts;
@ -9,10 +10,10 @@ public class AssembleIssueRequestEditInput : SfsStoreRequestCreateOrUpdateInputB
#region Base
/// <summary>
/// 叫料类型
/// 叫料类型
/// </summary>
[Display(Name = "叫料类型")]
public string Type { get; set; }
public EnumIssueRequestType IssueRequestType { get; set; }
/// <summary>
/// 使用在途库
@ -24,7 +25,7 @@ public class AssembleIssueRequestEditInput : SfsStoreRequestCreateOrUpdateInputB
/// 明细列表
/// </summary>
[Display(Name = "明细列表")]
public List<AssembleIssueRequestDetailInput> Details { get; set; } = new List<AssembleIssueRequestDetailInput>();
public List<KittingIssueRequestDetailInput> Details { get; set; } = new List<KittingIssueRequestDetailInput>();
#endregion
#region Create

12
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/IssueRequest/AssembleIssueRequests/Inputs/AssembleIssueRequestImportInput.cs

@ -1,22 +1,18 @@
using System.ComponentModel.DataAnnotations;
using Win_in.Sfs.Shared.Application.Contracts;
using Win_in.Sfs.Shared.Domain.Shared;
using Win_in.Sfs.Shared.Domain.Shared.Enums.Store;
namespace Win_in.Sfs.Wms.Store.Application.Contracts;
[Display(Name = "叫料申请")]
[Display(Name = "叫料申请导入")]
public class AssembleIssueRequestImportInput : SfsStoreImportInputBase
{
/// <summary>
/// 叫料类型
/// 叫料类型
/// </summary>
[Display(Name = "叫料类型")]
[Required(ErrorMessage = "{0}是必填项")]
[ImporterHeader(Name = "叫料类型")]
[ExporterHeader(DisplayName = "叫料类型")]
[ValueMapping("人工拉动", EnumMaterialRequestType.Issue_Manual)]
public string Type { get; set; }
public EnumIssueRequestType IssueRequestType { get; set; }
/// <summary>
/// 物品代码

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

@ -3,21 +3,29 @@ using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Linq.Expressions;
using System.Net.Http.Headers;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Castle.Components.DictionaryAdapter;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using MyNamespace;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Win_in.Sfs.Basedata.Application.Contracts;
using Win_in.Sfs.Basedata.Domain.Shared;
using Win_in.Sfs.Shared.Domain;
using Win_in.Sfs.Shared.Domain.Shared;
using Win_in.Sfs.Shared.Domain.Shared.Enums.Store;
using Win_in.Sfs.Wms.Inventory.Application.Contracts;
using Win_in.Sfs.Wms.Store.Application.Contracts;
using Win_in.Sfs.Wms.Store.Domain;
using Win_in.Sfs.Wms.Store.Domain.Shared;
using Win_in.Sfs.Wms.Store.Jobs.IssueJobs.proxy;
using Win_in.Sfs.Wms.Store.Notes;
using Win_in.Sfs.Wms.Store.Options;
namespace Win_in.Sfs.Wms.Store.Application;
@ -28,17 +36,36 @@ public class AssembleIssueJobAppService
AssembleIssueJobCheckInput, AssembleIssueJobEditInput>,
IAssembleIssueJobAppService, ITransferLibCallback
{
private readonly IAssembleIssueJobManager _assembleJobManager;
private readonly IAssembleIssueJobManager _assembleIssueJobManager;
private readonly ILocationAppService _locationAppService;
private readonly ITransferLibJobAppService _transferLibJobAppService;
private readonly IAssembleIssueNoteAppService _assembleIssueNoteAppService;
private readonly IExpectOutAppService _expectOutAppService;
private readonly IHttpClientFactory _httpClientFactory;
private readonly IOptions<RestoOptions> _options;
protected IAssembleIssueRequestAppService AssembleIssueRequestAppService =>
LazyServiceProvider.LazyGetRequiredService<IAssembleIssueRequestAppService>();
public AssembleIssueJobAppService(
IAssembleIssueJobRepository repository, IAssembleIssueJobManager assembleJobManager,
ILocationAppService locationAppService, ITransferLibJobAppService transferLibJobAppService) : base(repository, assembleJobManager)
IAssembleIssueJobRepository repository, IAssembleIssueJobManager assembleIssueJobManager,
ILocationAppService locationAppService, ITransferLibJobAppService transferLibJobAppService,
IAssembleIssueNoteAppService assembleIssueNoteAppService, IExpectOutAppService expectOutAppService
, IHttpClientFactory httpClientFactory
, IOptions<RestoOptions> options
) : base(
repository, assembleIssueJobManager)
{
_assembleJobManager = assembleJobManager;
_assembleIssueJobManager = assembleIssueJobManager;
_locationAppService = locationAppService;
_transferLibJobAppService = transferLibJobAppService;
_assembleIssueNoteAppService = assembleIssueNoteAppService;
_expectOutAppService = expectOutAppService;
_httpClientFactory = httpClientFactory;
_options = options;
}
[HttpPost("add-many")]
@ -47,17 +74,183 @@ public class AssembleIssueJobAppService
foreach (var input in inputs)
{
await CheckMinRowAndSetStatusAsync(input).ConfigureAwait(false);
await CheckDimensionalStorehouseAsync(input).ConfigureAwait(false);
}
var assembleIssueJobDtos = await base.CreateManyAsync(inputs).ConfigureAwait(false);
foreach (var assembleIssueJobDto in assembleIssueJobDtos)
{
await CheckDimensionalStorehouseAsync(assembleIssueJobDto).ConfigureAwait(false);
}
return await base.CreateManyAsync(inputs).ConfigureAwait(false);
return assembleIssueJobDtos;
}
[HttpPost("")]
public override async Task<AssembleIssueJobDTO> CreateAsync(AssembleIssueJobEditInput input)
{
await CheckMinRowAndSetStatusAsync(input).ConfigureAwait(false);
await CheckDimensionalStorehouseAsync(input).ConfigureAwait(false);
var assembleIssueJobDto = await base.CreateAsync(input).ConfigureAwait(false);
await CheckDimensionalStorehouseAsync(assembleIssueJobDto).ConfigureAwait(false);
return assembleIssueJobDto;
}
[HttpPost("invalid")]
public override async Task CancelAsync(Guid id)
{
var injectionJob = await _repository.GetAsync(id).ConfigureAwait(false);
if (injectionJob == null)
{
throw new UserFriendlyException($"未找到ID为 {id} 的任务");
}
await _assembleIssueJobManager.CancelAsync(injectionJob).ConfigureAwait(false);
}
[HttpPost("cancel-by-request/{requestNumber}")]
public virtual async Task CancelByMaterialRequestAsync(string requestNumber)
{
var entities = await _repository.GetListAsync(p => p.AssembleRequestNumber == requestNumber)
.ConfigureAwait(false);
foreach (var entity in entities)
{
await _assembleIssueJobManager.CancelAsync(entity).ConfigureAwait(false);
}
}
return await base.CreateAsync(input).ConfigureAwait(false);
[HttpPost("by-request-number/{requestNumber}")]
public virtual async Task<List<AssembleIssueJobDTO>> GetByRequestNumberAsync(string requestNumber)
{
var entitys = await _repository.GetListAsync(p => p.AssembleRequestNumber == requestNumber)
.ConfigureAwait(false);
return ObjectMapper.Map<List<AssembleIssueJob>, List<AssembleIssueJobDTO>>(entitys);
}
/// <summary>
/// 库移回调
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
[HttpPost("Do-Call-Back")]
public async Task DoTransferLibCallbackAsync(TransferLibJobDTO dto)
{
var job = await _repository.FindAsync(p => p.Number == dto.CallJobNumber).ConfigureAwait(false);
var transferLibJobDto = await _transferLibJobAppService.GetByNumberAsync(dto.Number).ConfigureAwait(false);
var transferLibNoteDetail = dto.Details.First();
var jobDetail = job.Details.First();
job.JobStatus = EnumJobStatus.Open;
jobDetail.TransferLibFromArriveDate = transferLibNoteDetail.HandledFromArriveDate;
jobDetail.TransferLibFromContainerCode = transferLibNoteDetail.HandledFromContainerCode;
jobDetail.TransferLibFromExpireDate = transferLibNoteDetail.HandledFromExpireDate;
jobDetail.TransferLibFromLocationArea = transferLibNoteDetail.HandledFromLocationArea;
jobDetail.TransferLibFromLocationCode = transferLibNoteDetail.HandledFromLocationCode;
jobDetail.TransferLibFromLocationErpCode = transferLibNoteDetail.HandledFromLocationErpCode;
jobDetail.TransferLibFromLocationGroup = transferLibNoteDetail.HandledFromLocationGroup;
jobDetail.TransferLibFromLot = transferLibNoteDetail.HandledFromLot;
jobDetail.TransferLibFromPackingCode = transferLibNoteDetail.HandledFromPackingCode;
jobDetail.TransferLibFromProduceDate = transferLibNoteDetail.HandledFromProduceDate;
jobDetail.TransferLibFromQty = transferLibNoteDetail.HandledFromQty;
jobDetail.TransferLibFromSupplierBatch = transferLibNoteDetail.HandledFromSupplierBatch;
jobDetail.TransferLibFromWarehouseCode = transferLibNoteDetail.HandledFromWarehouseCode;
jobDetail.TransferLibToArriveDate = transferLibNoteDetail.HandledToArriveDate;
jobDetail.TransferLibToContainerCode = transferLibNoteDetail.HandledToContainerCode;
jobDetail.TransferLibToExpireDate = transferLibNoteDetail.HandledToExpireDate;
jobDetail.TransferLibToLocationArea = transferLibNoteDetail.HandledToLocationArea;
jobDetail.TransferLibToLocationCode = transferLibNoteDetail.HandledToLocationCode;
jobDetail.TransferLibToLocationErpCode = transferLibNoteDetail.HandledToLocationErpCode;
jobDetail.TransferLibToLocationGroup = transferLibNoteDetail.HandledToLocationGroup;
jobDetail.TransferLibToLot = transferLibNoteDetail.HandledToLot;
jobDetail.TransferLibToPackingCode = transferLibNoteDetail.HandledToPackingCode;
jobDetail.TransferLibToProduceDate = transferLibNoteDetail.HandledToProduceDate;
jobDetail.TransferLibToQty = transferLibNoteDetail.HandledToQty;
jobDetail.TransferLibToSupplierBatch = transferLibNoteDetail.HandledToSupplierBatch;
jobDetail.TransferLibToWarehouseCode = transferLibNoteDetail.HandledToWarehouseCode;
await _repository.UpdateAsync(job).ConfigureAwait(false);
}
/// <summary>
/// 执行任务明细
/// </summary>
/// <returns></returns>
[HttpPost("ExecuteDetail/{masterId}")]
public async Task ExecuteDetailAsync(Guid masterId, Guid detailId, AssembleIssueJobDetailDTO issueJobDetailDto)
{
var assembleIssueJob = await _repository.GetAsync(masterId).ConfigureAwait(false);
assembleIssueJob.JobStatus = EnumJobStatus.Doing;
var assembleIssueJobDto = ObjectMapper.Map<AssembleIssueJob, AssembleIssueJobDTO>(assembleIssueJob);
assembleIssueJobDto.Details = new List<AssembleIssueJobDetailDTO> { issueJobDetailDto };
var assembleIssueNoteEditInput = await BuildAssembleIssueNoteAsync(assembleIssueJobDto).ConfigureAwait(false);
await _assembleIssueNoteAppService.CreateAsync(assembleIssueNoteEditInput).ConfigureAwait(false);
var issueJobDetail = ObjectMapper.Map<AssembleIssueJobDetailDTO, AssembleIssueJobDetail>(issueJobDetailDto);
var entityDetail = assembleIssueJob.Details.Find(p => p.Id == detailId);
issueJobDetail.HandledFromQty = entityDetail.HandledFromQty;
issueJobDetail.HandledToQty = entityDetail.HandledToQty;
issueJobDetail.HandledToQty += issueJobDetailDto.HandledToQty;
issueJobDetail.HandledFromQty += issueJobDetailDto.HandledFromQty;
assembleIssueJob.Details = new EditableList<AssembleIssueJobDetail>() { issueJobDetail };
if (assembleIssueJob.EnumIssueSendType == EnumIssueSendType.BoxQtyType) //按箱叫料 因为任务只有1箱 所以可以直接完成
{
await UpdateRequestAndjobStatusDoneAsync(assembleIssueJob, issueJobDetailDto, issueJobDetailDto.HandledToQty).ConfigureAwait(false);
}
else
{
var detail = assembleIssueJob.Details.First(p => p.Id == issueJobDetailDto.Id);
if (issueJobDetail.HandledToQty >= detail.RequestQty)
{
await UpdateRequestAndjobStatusDoneAsync(assembleIssueJob, issueJobDetailDto, issueJobDetailDto.HandledToQty).ConfigureAwait(false);
}
}
await _repository.UpdateAsync(assembleIssueJob).ConfigureAwait(false);
}
[HttpPost("CompleteAsync/{id}")]
public async Task CompleteAsync(Guid id)
{
var assembleIssueJob = await _repository.FindAsync(id).ConfigureAwait(false);
assembleIssueJob.JobStatus = EnumJobStatus.Done;
await _expectOutAppService.RemoveByNumberAndInventoryAsync(assembleIssueJob.Number,
assembleIssueJob.Details.First().ItemCode,
assembleIssueJob.Details.First().HandledToLocationCode, assembleIssueJob.Details.First().HandledToPackingCode,
assembleIssueJob.Details.First().Status, assembleIssueJob.Details.First().HandledToLot,
assembleIssueJob.Details.First().HandledToQty).ConfigureAwait(false);
await _expectOutAppService.RemoveByNumberAsync(assembleIssueJob.Number).ConfigureAwait(false);
await _repository.UpdateAsync(assembleIssueJob).ConfigureAwait(false);
}
#region 私有
/// <summary>
/// 创建补料记录实体
/// </summary>
/// <param name="assembleIssueJobDto"></param>
/// <returns></returns>
private async Task<AssembleIssueNoteEditInput> BuildAssembleIssueNoteAsync(AssembleIssueJobDTO assembleIssueJobDto)
{
var assembleIssueNoteCreateInput =
ObjectMapper.Map<AssembleIssueJobDTO, AssembleIssueNoteEditInput>(assembleIssueJobDto);
assembleIssueNoteCreateInput.JobNumber = assembleIssueJobDto.Number;
await Task.CompletedTask.ConfigureAwait(false);
return assembleIssueNoteCreateInput;
}
/// <summary>
@ -75,7 +268,9 @@ public class AssembleIssueJobAppService
if (loctionDto.Type == EnumLocationType.RAW && loctionDto.RowCode != 1)
{
input.JobStatus = EnumJobStatus.Wait;
}
else if (loctionDto.Type == EnumLocationType.RAW && loctionDto.RowCode == 1)
{
jobDetailInputdetail.TransferLibFromArriveDate = jobDetailInputdetail.RecommendFromArriveDate;
jobDetailInputdetail.TransferLibFromContainerCode = jobDetailInputdetail.RecommendFromContainerCode;
jobDetailInputdetail.TransferLibFromExpireDate = jobDetailInputdetail.RecommendFromExpireDate;
@ -93,101 +288,247 @@ public class AssembleIssueJobAppService
jobDetailInputdetail.TransferLibToArriveDate = jobDetailInputdetail.RecommendToArriveDate;
jobDetailInputdetail.TransferLibToContainerCode = jobDetailInputdetail.RecommendToContainerCode;
jobDetailInputdetail.TransferLibToExpireDate = jobDetailInputdetail.RecommendToExpireDate;
jobDetailInputdetail.TransferLibToLocationArea = jobDetailInputdetail.RecommendToLocationArea;
jobDetailInputdetail.TransferLibToLocationCode = jobDetailInputdetail.RecommendToLocationCode;
jobDetailInputdetail.TransferLibToLocationErpCode = jobDetailInputdetail.RecommendToLocationErpCode;
jobDetailInputdetail.TransferLibToLocationGroup = jobDetailInputdetail.RecommendToLocationGroup;
jobDetailInputdetail.TransferLibToLot = jobDetailInputdetail.RecommendToLot;
jobDetailInputdetail.TransferLibToPackingCode = jobDetailInputdetail.RecommendToPackingCode;
jobDetailInputdetail.TransferLibToProduceDate = jobDetailInputdetail.RecommendToProduceDate;
jobDetailInputdetail.TransferLibToQty = jobDetailInputdetail.RecommendToQty;
jobDetailInputdetail.TransferLibToSupplierBatch = jobDetailInputdetail.RecommendToSupplierBatch;
jobDetailInputdetail.TransferLibToWarehouseCode = jobDetailInputdetail.RecommendToWarehouseCode;
jobDetailInputdetail.TransferLibToWarehouseCode = jobDetailInputdetail.TransferLibFromWarehouseCode;
jobDetailInputdetail.TransferLibToLocationArea = jobDetailInputdetail.TransferLibFromLocationArea;
jobDetailInputdetail.TransferLibToLocationCode = jobDetailInputdetail.TransferLibFromLocationCode;
jobDetailInputdetail.TransferLibToLocationErpCode = jobDetailInputdetail.TransferLibFromLocationErpCode;
jobDetailInputdetail.TransferLibToLocationGroup = jobDetailInputdetail.TransferLibFromLocationGroup;
}
}
[HttpPost("cancel-by-request/{assembleRequestNumber}")]
public virtual async Task CancelByMaterialRequestAsync(string assembleNumber)
/// <summary>
/// 判断是不是在立体库
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
private async Task CheckDimensionalStorehouseAsync(AssembleIssueJobEditInput input)
{
var entities = await _repository.GetListAsync(p => p.AssembleRequestNumber == assembleNumber)
var jobDetailInputdetail = input.Details.FirstOrDefault();
var loctionDto = await _locationAppService.GetByCodeAsync(jobDetailInputdetail.RecommendFromLocationCode)
.ConfigureAwait(false);
foreach (var entity in entities)
if (loctionDto.Type == EnumLocationType.DimensionalStorehouse)
{
await _assembleJobManager.CancelAsync(entity).ConfigureAwait(false);
input.JobStatus = EnumJobStatus.Wait;
}
}
[HttpPost("invalid")]
public override async Task CancelAsync(Guid id)
/// <summary>
/// 判断是不是在立体库
/// </summary>
/// <param name="assembleIssueJobDto"></param>
/// <returns></returns>
private async Task CheckDimensionalStorehouseAsync(AssembleIssueJobDTO assembleIssueJobDto)
{
var assembleJob = await _repository.GetAsync(id).ConfigureAwait(false);
if (assembleJob == null)
var jobDetailInputdetail = assembleIssueJobDto.Details.FirstOrDefault();
var loctionDto = await _locationAppService.GetByCodeAsync(jobDetailInputdetail.RecommendFromLocationCode)
.ConfigureAwait(false);
if (loctionDto.Type == EnumLocationType.DimensionalStorehouse)
{
throw new UserFriendlyException($"未找到ID为 {id} 的任务");
//TODO 立体库
var ret = await SyncIssueJobStereoAsync(new List<AssembleIssueJobDTO> { assembleIssueJobDto }, loctionDto.Code).ConfigureAwait(false);
if (ret.Code != "1")
{
throw new UserFriendlyException($"调用立体库不成功!原因:{ret.Message}");
}
}
await _assembleJobManager.CancelAsync(assembleJob).ConfigureAwait(false);
}
[HttpPost("by-request-number/{requestNumber}")]
public virtual async Task<List<AssembleIssueJobDTO>> GetByRequestNumberAsync(string requestNumber)
/// <summary>
/// 修改当前任务状态 和 该任务的请求状态
/// </summary>
/// <param name="assembleIssueJob"></param>
/// <param name="assembleIssueJobDetailDto"></param>
/// <returns></returns>
/// <exception cref="UserFriendlyException"></exception>
private async Task UpdateRequestAndjobStatusDoneAsync(AssembleIssueJob assembleIssueJob,
AssembleIssueJobDetailDTO assembleIssueJobDetailDto, decimal handledToQty)
{
var entitys = await _repository.GetListAsync(p => p.AssembleRequestNumber == requestNumber)
if (assembleIssueJob.JobStatus is EnumJobStatus.Closed or EnumJobStatus.Cancelled or EnumJobStatus.None
or EnumJobStatus.Done) //需要考虑下 多次提交的问题 所以不判断 进行中
{
throw new UserFriendlyException(
$"任务状态错误:编号为【{assembleIssueJob.Number}】的任务状态为【{assembleIssueJob.JobStatus.GetDisplayName()}】");
}
assembleIssueJob.JobStatus = EnumJobStatus.Done;
await _expectOutAppService.RemoveByNumberAndInventoryAsync(assembleIssueJob.Number,
assembleIssueJobDetailDto.ItemCode,
assembleIssueJobDetailDto.HandledToLocationCode, assembleIssueJobDetailDto.HandledToPackingCode,
assembleIssueJobDetailDto.Status, assembleIssueJobDetailDto.HandledToLot,
handledToQty).ConfigureAwait(false);
//await _expectOutAppService.RemoveByNumberAsync(assembleIssueJob.Number).ConfigureAwait(false);
await AssembleIssueRequestAppService.UpdateStatusCompletedAsync(assembleIssueJob.AssembleRequestNumber)
.ConfigureAwait(false);
return ObjectMapper.Map<List<AssembleIssueJob>, List<AssembleIssueJobDTO>>(entitys);
await Task.CompletedTask.ConfigureAwait(false);
}
[HttpPost("Do-Call-Back")]
public async Task DoTransferLibCallbackAsync(TransferLibJobDTO dto)
{
var job = await _repository.FindAsync(p => p.Number == dto.JobNumber).ConfigureAwait(false);
//todo 等云峰写好换成真实的
var transferLibJobDto = await _transferLibJobAppService.GetByNumberAsync("AAA").ConfigureAwait(false);
var transferLibNote = new TransferLibNote();
var transferLibNoteDetail = transferLibNote.Details.First();
var jobDetail = job.Details.First();
job.JobStatus = EnumJobStatus.Open;
/// <summary>
/// 立体库同步
/// </summary>
/// <param name="input"></param>
/// <param name="p_loc"></param>
/// <returns></returns>
[HttpPost("sync-issue-job-stereo")]
jobDetail.TransferLibFromArriveDate = transferLibNoteDetail.HandledFromArriveDate;
jobDetail.TransferLibFromContainerCode = transferLibNoteDetail.HandledFromContainerCode;
jobDetail.TransferLibFromExpireDate = transferLibNoteDetail.HandledFromExpireDate;
jobDetail.TransferLibFromLocationArea = transferLibNoteDetail.HandledFromLocationArea;
jobDetail.TransferLibFromLocationCode = transferLibNoteDetail.HandledFromLocationCode;
jobDetail.TransferLibFromLocationErpCode = transferLibNoteDetail.HandledFromLocationErpCode;
jobDetail.TransferLibFromLocationGroup = transferLibNoteDetail.HandledFromLocationGroup;
jobDetail.TransferLibFromLot = transferLibNoteDetail.HandledFromLot;
jobDetail.TransferLibFromPackingCode = transferLibNoteDetail.HandledFromPackingCode;
jobDetail.TransferLibFromProduceDate = transferLibNoteDetail.HandledFromProduceDate;
jobDetail.TransferLibFromQty = transferLibNoteDetail.HandledFromQty;
jobDetail.TransferLibFromSupplierBatch = transferLibNoteDetail.HandledFromSupplierBatch;
jobDetail.TransferLibFromWarehouseCode = transferLibNoteDetail.HandledFromWarehouseCode;
public async Task<ReusltObject> SyncIssueJobStereoAsync(List<AssembleIssueJobDTO> input, string p_loc)
{
ReusltObject ret = new ReusltObject();
ret.Code = "1";
ret.Message = "操作成功";
ret.OperateTime = DateTime.Now.ToString("yyyy-MM-dd");
try
{
List<IssueJobToRestoDetailDTO> IssueJobToRestoDetailDTOs = new List<IssueJobToRestoDetailDTO>();
IssueJobToRestoDTO main = new IssueJobToRestoDTO();
main.OperatorName = CurrentUser.UserName;
foreach (var job in input)
{
foreach (var jobitem in job.Details)
{
IssueJobToRestoDetailDTOs.Add(new IssueJobToRestoDetailDTO()
{
Count = jobitem.HandledToQty,
ProductNo = jobitem.ItemCode,
NeedSite = p_loc,
WorkNo = job.Number,
TaskNo = job.Number
});
}
}
main.Details = IssueJobToRestoDetailDTOs;
var httpclient = _httpClientFactory.CreateClient();
#if DEBUG
jobDetail.TransferLibToArriveDate = transferLibNoteDetail.HandledToArriveDate;
jobDetail.TransferLibToContainerCode = transferLibNoteDetail.HandledToContainerCode;
jobDetail.TransferLibToExpireDate = transferLibNoteDetail.HandledToExpireDate;
jobDetail.TransferLibToLocationArea = transferLibNoteDetail.HandledToLocationArea;
jobDetail.TransferLibToLocationCode = transferLibNoteDetail.HandledToLocationCode;
jobDetail.TransferLibToLocationErpCode = transferLibNoteDetail.HandledToLocationErpCode;
jobDetail.TransferLibToLocationGroup = transferLibNoteDetail.HandledToLocationGroup;
jobDetail.TransferLibToLot = transferLibNoteDetail.HandledToLot;
jobDetail.TransferLibToPackingCode = transferLibNoteDetail.HandledToPackingCode;
jobDetail.TransferLibToProduceDate = transferLibNoteDetail.HandledToProduceDate;
jobDetail.TransferLibToQty = transferLibNoteDetail.HandledToQty;
jobDetail.TransferLibToSupplierBatch = transferLibNoteDetail.HandledToSupplierBatch;
jobDetail.TransferLibToWarehouseCode = transferLibNoteDetail.HandledToWarehouseCode;
string json = System.Text.Json.JsonSerializer.Serialize(main);
_options.Value.Address = "http://localhost:59094/";//测试地址
_options.Value.Token = "";//测试token
_options.Value.UserName = "";//测试用户名
_options.Value.Password = "";//测试密码
await _repository.UpdateAsync(job).ConfigureAwait(false);
#endif
if (!string.IsNullOrEmpty(_options.Value.Token))
{
var token = _options.Value.Token;
httpclient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
}
if (!string.IsNullOrEmpty(_options.Value.UserName) && !string.IsNullOrEmpty(_options.Value.Password))
{
var username = _options.Value.UserName;
var password = _options.Value.Password;
httpclient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(System.Text.Encoding.ASCII.GetBytes($"{username}:{password}")));
}
IssueJobToRestoClient client = new IssueJobToRestoClient(_options.Value.Address, httpclient);
ret = await client.SyncIssueJobStereoAsync(main).ConfigureAwait(false);
}
catch (Exception ex)
{
ret = new ReusltObject();
ret.Code = "2";
ret.Message = ex.Message;
ret.OperateTime = DateTime.Now.ToString("yyyy-MM-dd");
}
return ret;
return;
}
[HttpPost("test")]
public virtual async Task Test()
[HttpPost("receive-issue-job-stereo")]
public virtual async Task<ReusltObject> SyncReciveIssueJobStereoAsync(IssueRequestFromRestoDTO input)
{
Console.WriteLine("FuAZCZXVZXVXZVZ");
await Task.CompletedTask;
#if DEBUG
var json = System.Text.Json.JsonSerializer.Serialize(input);
#endif
List<string> errors = new List<string>();
var ret = new ReusltObject()
{
Code = "1",
OperateTime = DateTime.Now.ToString("yyyy-MM-dd"),
Message = "操作成功"
};
try
{
if (input.Jobs.Count > 0)
{
var jobs = input.Jobs;
var numbers = jobs.Select(p => p.JobNumber);
var query = _repository.WithDetails()
.Where(p => numbers.Contains(p.Number));
var entities = query.ToList();
var dtos = ObjectMapper.Map<List<AssembleIssueJob>, List<AssembleIssueJobDTO>>(entities);
if (input.Jobs.Count == entities.Count)
{
errors.Add("立体库提交出库任务和WMS任务不符,请核对! \n");
}
foreach (var itm in dtos)
{
var first = jobs.FirstOrDefault<IssueJobFromRestoDTO>(p => p.JobNumber == itm.Number);
var itmDetails = itm.Details.ToList();
List<AssembleIssueJobDetailDTO> details = new List<AssembleIssueJobDetailDTO>();
foreach (var detail in first.Details)
{
var entity = itmDetails.FirstOrDefault(p => p.ItemCode == detail.ItemCode);
AssembleIssueJobDetailDTO dto = new AssembleIssueJobDetailDTO();
dto.HandledFromLocationCode = entity.HandledFromLocationCode;
dto.HandledToLocationCode = entity.HandledToLocationCode;
dto.ItemCode = detail.ItemCode;
dto.RecommendFromQty = detail.Qty;
dto.RecommendToQty = detail.Qty;
dto.HandledFromQty = detail.Qty;
dto.HandledToQty = detail.Qty;
dto.Status = entity.Status;
details.Add(dto);
}
itm.Details = details;
await CompleteAsync(itm.Id, itm).ConfigureAwait(false);
}
}
else
{
errors.Add("立体库确认单据里无数据! \n");
}
}
catch (Exception ex)
{
ret = new ReusltObject()
{
Code = "2",
OperateTime = DateTime.Now.ToString("yyyy-MM-dd"),
Message = ex.Message
};
return ret;
}
if (errors.Count > 0)
{
ret = new ReusltObject()
{
Code = "2",
OperateTime = DateTime.Now.ToString("yyyy-MM-dd"),
Message = string.Join(",", errors.ToArray())
};
}
return ret;
}
#endregion
}

21
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Notes/IssueNotes/AssembleIssueNotes/AssembleIssueNoteAppService.cs

@ -18,20 +18,20 @@ using Win_in.Sfs.Wms.Store.Domain.Shared;
namespace Win_in.Sfs.Wms.Store.Application;
[Authorize]
[Route($"{StoreConsts.RootPath}assemble-note")]
[Route($"{StoreConsts.RootPath}assemble-issue-note")]
public class AssembleIssueNoteAppService :
SfsStoreWithDetailsAppServiceBase<AssembleIssueNote, AssembleIssueNoteDTO, SfsStoreRequestInputBase, AssembleIssueNoteEditInput, AssembleIssueNoteDetail,
AssembleIssueNoteDetailDTO, SfsStoreRequestInputBase, AssembleIssueNoteImportInput>,
IAssembleIssueNoteAppService
{
private readonly IAssembleIssueNoteManager _assembleNoteManager;
private readonly IAssembleIssueNoteManager _assembleIssueNoteManager;
public AssembleIssueNoteAppService(
IAssembleIssueNoteRepository repository,
IAssembleIssueNoteManager assembleNoteManager
IAssembleIssueNoteManager assembleIssueNoteManager
) : base(repository)
{
_assembleNoteManager = assembleNoteManager;
_assembleIssueNoteManager = assembleIssueNoteManager;
}
[HttpPost("")]
@ -39,7 +39,7 @@ public class AssembleIssueNoteAppService :
public override async Task<AssembleIssueNoteDTO> CreateAsync(AssembleIssueNoteEditInput input)
{
var entity = ObjectMapper.Map<AssembleIssueNoteEditInput, AssembleIssueNote>(input);
await _assembleNoteManager.CreateAsync(entity).ConfigureAwait(false);
await _assembleIssueNoteManager.CreateAsync(entity).ConfigureAwait(false);
var dto = ObjectMapper.Map<AssembleIssueNote, AssembleIssueNoteDTO>(entity);
return dto;
}
@ -52,10 +52,11 @@ public class AssembleIssueNoteAppService :
[HttpPost("confirm/{id}")]
public virtual async Task<AssembleIssueNoteDTO> ConfirmAsync(Guid id)
{
var assembleNote= await _repository.GetAsync(id).ConfigureAwait(false);
assembleNote.Confirmed = true;
assembleNote=await _repository.UpdateAsync(assembleNote).ConfigureAwait(false);
await LocalEventBus.PublishAsync(new SfsConfirmedEntityEventData<AssembleIssueNote>(assembleNote), false).ConfigureAwait(false);
return ObjectMapper.Map<AssembleIssueNote, AssembleIssueNoteDTO>(assembleNote);
var assembleIssueNote = await _repository.GetAsync(id).ConfigureAwait(false);
assembleIssueNote.Confirmed = true;
assembleIssueNote = await _repository.UpdateAsync(assembleIssueNote).ConfigureAwait(false);
await LocalEventBus.PublishAsync(new SfsConfirmedEntityEventData<AssembleIssueNote>(assembleIssueNote), false).ConfigureAwait(false);
return ObjectMapper.Map<AssembleIssueNote, AssembleIssueNoteDTO>(assembleIssueNote);
}
}

250
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Requests/IssuelRequests/AssembleIssueRequests/AssembleIssueRequestAppService.cs

@ -1,7 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Castle.Components.DictionaryAdapter;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using NUglify.Helpers;
using Volo.Abp;
using Win_in.Sfs.Basedata.Application.Contracts;
using Win_in.Sfs.Shared.Domain.Shared;
@ -12,39 +16,38 @@ using Win_in.Sfs.Wms.Store.Domain.Shared;
namespace Win_in.Sfs.Wms.Store.Application;
/// <summary>
/// 装配叫料
/// 装配叫料申请
/// </summary>
[Authorize]
[Route($"{StoreConsts.RootPath}assemble-request")]
public class AssembleIssueRequestAppService : SfsStoreRequestAppServiceBase<AssembleIssueRequest,
AssembleIssueRequestDTO,
SfsStoreRequestInputBase, AssembleIssueRequestEditInput, AssembleIssueRequestDetail,
AssembleIssueRequestDetailDTO,
[Route($"{StoreConsts.RootPath}assemble-issue-request")]
public class AssembleIssueRequestAppService : SfsStoreRequestAppServiceBase<AssembleIssueRequest, AssembleIssueRequestDTO,
SfsStoreRequestInputBase, AssembleIssueRequestEditInput, AssembleIssueRequestDetail, AssembleIssueRequestDetailDTO,
SfsStoreRequestInputBase, AssembleIssueRequestImportInput>,
IAssembleIssueRequestAppService
{
private readonly IAssembleIssueRequestManager _assembleRequestManager;
private readonly IAssembleIssueRequestManager _assembleIssueRequestManager;
private readonly IItemStoreRelationAppService _itemStoreRelationApp;
private readonly IAreaAppService _areaApp;
private readonly ILocationAppService _locationAppService;
private readonly IItemBasicAppService _itemBasicAppService;
private readonly IProductionLineAppService _productionLineAppService;
private readonly IAssembleIssueJobAppService _assembleIssueJobAppService;
private readonly ITransactionTypeAppService _transactionTypeAppService;
public AssembleIssueRequestAppService(
IAssembleIssueRequestRepository repository,
IAssembleIssueRequestManager assembleRequestManager,
IAssembleIssueRequestManager assembleIssueRequestManager,
IPreparationPlanManager preparationPlanManager,
IItemStoreRelationAppService itemStoreRelationApp,
IAreaAppService areaApp,
ILocationAppService locationAppService,
IItemBasicAppService itemBasicAppService,
IProductionLineAppService productionLineAppService,
ITransactionTypeAppService transactionTypeAppService
)
: base(repository, assembleRequestManager)
ITransactionTypeAppService transactionTypeAppService, IAssembleIssueJobAppService assembleIssueJobAppService)
: base(repository, assembleIssueRequestManager)
{
_assembleRequestManager = assembleRequestManager;
_assembleIssueRequestManager = assembleIssueRequestManager;
_itemStoreRelationApp = itemStoreRelationApp;
_areaApp = areaApp;
_locationAppService = locationAppService;
@ -52,13 +55,12 @@ public class AssembleIssueRequestAppService : SfsStoreRequestAppServiceBase<Asse
_productionLineAppService = productionLineAppService;
_transactionTypeAppService = transactionTypeAppService;
_assembleIssueJobAppService = assembleIssueJobAppService;
}
public override async Task<AssembleIssueRequestDTO> HandleAsync(Guid id)
{
await Task.CompletedTask.ConfigureAwait(false);
return null;
return await base.HandleAsync(id).ConfigureAwait(false);
}
[HttpPost("")]
@ -72,18 +74,21 @@ public class AssembleIssueRequestAppService : SfsStoreRequestAppServiceBase<Asse
}
}
foreach (var detailInput in input.Details) //赋值生产线
foreach (var detailInput in input.Details)
{
var toLocationDto =
await _locationAppService.GetByCodeAsync(detailInput.ToLocationCode).ConfigureAwait(false);
CheckLocation(toLocationDto, detailInput.ToLocationCode);
var itemBasicDto = await _itemBasicAppService.GetByCodeAsync(detailInput.ItemCode).ConfigureAwait(false);
CheckItemBasic(itemBasicDto, detailInput.ItemCode);
var productionLineDto = await _productionLineAppService.GetByLocationCodeAsync(detailInput.ToLocationCode).ConfigureAwait(false);
CheckProductionLine(productionLineDto, detailInput.ProdLine);
detailInput.ProdLine = productionLineDto.Code;
detailInput.ToLocationArea = toLocationDto.AreaCode;
detailInput.ToLocationGroup = toLocationDto.LocationGroupCode;
detailInput.ToWarehouseCode = toLocationDto.WarehouseCode;
detailInput.ProdLine = detailInput.ToLocationCode;
detailInput.ToLocationErpCode = toLocationDto.ErpLocationCode;
detailInput.ItemDesc1 = itemBasicDto.Desc1;
@ -95,12 +100,13 @@ public class AssembleIssueRequestAppService : SfsStoreRequestAppServiceBase<Asse
//因为是刚创建的 所以发料数一定是0
detailInput.IssuedQty = 0;
detailInput.RecommendType = EnumRecommendType.KITTING;
}
await SetRequestAutoPropertiesAsync(input).ConfigureAwait(false);
var entity = ObjectMapper.Map<AssembleIssueRequestEditInput, AssembleIssueRequest>(input);
var result = await _assembleRequestManager.CreateByNumberAsync(entity).ConfigureAwait(false);
var result = await _assembleIssueRequestManager.CreateByNumberAsync(entity).ConfigureAwait(false);
var dto = ObjectMapper.Map<AssembleIssueRequest, AssembleIssueRequestDTO>(result);
@ -127,16 +133,210 @@ public class AssembleIssueRequestAppService : SfsStoreRequestAppServiceBase<Asse
[HttpPost("create-and-handle")]
public async Task<AssembleIssueRequestDTO> CreateAndHandleAsync(AssembleIssueRequestEditInput input)
{
var assembleRequestDto = await CreateAsync(input).ConfigureAwait(false);
var assembleIssueRequestDto = await CreateAsync(input).ConfigureAwait(false);
await HandleAsync(assembleRequestDto.Id).ConfigureAwait(false);
//await HandleAsync(assembleIssueRequestDto.Id).ConfigureAwait(false);
return assembleIssueRequestDto;
}
public override async Task<AssembleIssueRequestDTO> CancelAsync(Guid id)
{
var request = await _repository.GetAsync(id).ConfigureAwait(false);
var list = await _assembleIssueJobAppService.GetByRequestNumberAsync(request.Number).ConfigureAwait(false);
if (list.Any())
{
foreach (var assembleIssueJobDto in list)
{
if (assembleIssueJobDto.JobStatus == EnumJobStatus.Open ||
assembleIssueJobDto.JobStatus == EnumJobStatus.Partial ||
assembleIssueJobDto.JobStatus == EnumJobStatus.Doing ||
assembleIssueJobDto.JobStatus == EnumJobStatus.Wait)
{
await _assembleIssueJobAppService.CancelAsync(assembleIssueJobDto.Id).ConfigureAwait(false);
}
}
}
return assembleRequestDto;
return await base.CancelAsync(id).ConfigureAwait(false);
}
[HttpPost("UpdateStatusCompleted")]
public async Task UpdateStatusCompletedAsync(string number)
{
var assembleIssueRequest = await _repository.FindAsync(p => p.Number == number).ConfigureAwait(false);
await UpdateAssembleIssueRequestDetailQtyAsync(assembleIssueRequest, new EditableList<AssembleIssueJobDTO>()).ConfigureAwait(false);
var assembleIssueJobDtos = await _assembleIssueJobAppService.GetByRequestNumberAsync(assembleIssueRequest.Number).ConfigureAwait(false);
if (assembleIssueJobDtos.Any(p =>
p.JobStatus == EnumJobStatus.Open || p.JobStatus == EnumJobStatus.Doing ||
p.JobStatus == EnumJobStatus.Partial))
{
return;
}
else
{
bool flag = true;
foreach (var detail in assembleIssueRequest.Details)
{
if (detail.Qty >= detail.IssuedQty)
{
flag = false;
return;
}
}
if (flag)
{
CheckStatus(EnumRequestStatus.Completed, assembleIssueRequest.RequestStatus);
assembleIssueRequest.RequestStatus = EnumRequestStatus.Completed;
await _repository.UpdateAsync(assembleIssueRequest).ConfigureAwait(false);
}
}
}
/// <summary>
/// 修改请求的 已发 已收数量
/// </summary>
/// <param name="assembleIssueRequest"></param>
/// <param name="addAssembleIssueJobDtos"></param>
/// <returns></returns>
private async Task UpdateAssembleIssueRequestDetailQtyAsync(AssembleIssueRequest assembleIssueRequest,
List<AssembleIssueJobDTO> addAssembleIssueJobDtos)
{
//原有任务
var existAssembleIssueJobDtos = await _assembleIssueJobAppService.GetByRequestNumberAsync(assembleIssueRequest.Number)
.ConfigureAwait(false);
//新增的任务和已有的任务总和
var allAssembleIssueJobDtos = new List<AssembleIssueJobDTO>();
allAssembleIssueJobDtos.AddRange(addAssembleIssueJobDtos);
allAssembleIssueJobDtos.AddRange(existAssembleIssueJobDtos);
var groupByItemCodeLocationCode = assembleIssueRequest.Details.GroupBy(p =>
new { p.ItemCode, p.ToLocationCode });
foreach (var group in groupByItemCodeLocationCode)
{
foreach (var requestDetail in group)
{
//所有已发数量
decimal allIssuedQty = 0;
//所有已发数量
decimal allReceivedQty = 0;
foreach (var allAssembleIssueJobDto in allAssembleIssueJobDtos)
{
var jobDetailDtos = allAssembleIssueJobDto.Details.Where(p =>
p.ItemCode == group.Key.ItemCode && p.RequestLocationCode == group.Key.ToLocationCode);
//所有已发数量
allIssuedQty += jobDetailDtos.Sum(p => p.RequestQty);
//所有已发数量
allReceivedQty += jobDetailDtos.Sum(p => p.HandledToQty);
}
requestDetail.IssuedQty += allIssuedQty;
requestDetail.ReceivedQty += allReceivedQty;
}
}
await _repository.UpdateAsync(assembleIssueRequest).ConfigureAwait(false);
}
[HttpPost("IsHasNewJob")]
public async Task<string> IsHasNewJobAsync(string requestNumber, List<string> jobNumber)
{
var joblIssueJobDtos = await _assembleIssueJobAppService.GetByRequestNumberAsync(requestNumber).ConfigureAwait(false);
if (joblIssueJobDtos != null && joblIssueJobDtos.Any())
{
var jobNumberList = joblIssueJobDtos.Select(p => p.Number);
var difference = jobNumberList.Except(jobNumber);
if (difference.Any())
{
var result = "已生成任务号";
difference.ForEach(p => result += "【" + p + "】");
result += "的任务";
return result;
}
else
{
return "无任务生成,请检查库存";
}
}
else
{
return "无任务生成,请检查库存";
}
}
#region 校验
private void CheckStatus(EnumRequestStatus targetStatus, EnumRequestStatus nowStatus)
{
var validSourceStatuses = new List<EnumRequestStatus>();
switch (targetStatus)
{
case EnumRequestStatus.None:
break;
case EnumRequestStatus.New:
break;
case EnumRequestStatus.Reviewing:
validSourceStatuses = new List<EnumRequestStatus> { EnumRequestStatus.New };
break;
case EnumRequestStatus.Refused:
validSourceStatuses = new List<EnumRequestStatus> { EnumRequestStatus.Reviewing };
break;
case EnumRequestStatus.Agreed:
validSourceStatuses = new List<EnumRequestStatus> { EnumRequestStatus.Reviewing };
break;
case EnumRequestStatus.Handling:
validSourceStatuses = new List<EnumRequestStatus>
{
EnumRequestStatus.Agreed, EnumRequestStatus.Partial,
};
break;
case EnumRequestStatus.Completed:
validSourceStatuses = new List<EnumRequestStatus>
{
EnumRequestStatus.Handling, EnumRequestStatus.Partial,
};
break;
case EnumRequestStatus.Cancelled:
validSourceStatuses = new List<EnumRequestStatus>
{
EnumRequestStatus.New, EnumRequestStatus.Reviewing, EnumRequestStatus.Agreed,
};
break;
case EnumRequestStatus.Abort:
validSourceStatuses = new List<EnumRequestStatus>
{
EnumRequestStatus.Handling, EnumRequestStatus.Partial,
};
break;
case EnumRequestStatus.Partial:
{
validSourceStatuses = new List<EnumRequestStatus>
{
EnumRequestStatus.Handling, EnumRequestStatus.Partial,
};
break;
}
default:
throw new ArgumentOutOfRangeException(nameof(targetStatus), targetStatus, null);
}
if (!validSourceStatuses.Contains(nowStatus))
{
throw new UserFriendlyException(
$"当前状态为 {nowStatus.GetDisplayName()} ,无法变更为 {targetStatus.GetDisplayName()}");
}
}
private void CheckItemBasic(ItemBasicDTO itemBasicDto, string itemCode)
{
if (itemBasicDto == null)
@ -158,5 +358,13 @@ public class AssembleIssueRequestAppService : SfsStoreRequestAppServiceBase<Asse
}
}
private void CheckProductionLine(ProductionLineDTO productionLineDto, string productionCode)
{
if (productionLineDto == null)
{
throw new UserFriendlyException($"未找到生产线【{productionCode}】");
}
}
#endregion
}

3
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/IssueJobs/AssembleIssueJobs/AssembleIssueJob.cs

@ -13,7 +13,6 @@ namespace Win_in.Sfs.Wms.Store.Domain;
[Display(Name = "装配发料任务")]
public class AssembleIssueJob : SfsJobAggregateRootBase<AssembleIssueJobDetail>
{
/// <summary>
/// 叫料类型
/// </summary>
@ -44,6 +43,6 @@ public class AssembleIssueJob : SfsJobAggregateRootBase<AssembleIssueJobDetail>
/// </summary>
[IgnoreUpdate]
public override List<AssembleIssueJobDetail> Details { get; set; } = new List<AssembleIssueJobDetail>();
public EnumIssueSendType EnumIssueSendType { get; set; }
}

2
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/IssueJobs/AssembleIssueJobs/AssembleIssueJobDetail.cs

@ -8,7 +8,6 @@ namespace Win_in.Sfs.Wms.Store.Domain;
public class AssembleIssueJobDetail : SfsDetailEntityBase
{
#region 库存基础信息
/// <summary>
@ -522,4 +521,5 @@ public class AssembleIssueJobDetail : SfsDetailEntityBase
{
this.Id = id;
}
}

5
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/IssueJobs/AssembleIssueJobs/AssembleIssueJobManager.cs

@ -18,7 +18,9 @@ public class AssembleIssueJobManager : SfsJobManagerBase<AssembleIssueJob, Assem
private readonly IExpectOutAppService _expectOutAppService;
public AssembleIssueJobManager(
IAssembleIssueJobRepository repository, IBalanceAppService balanceAppService, IExpectOutAppService expectOutAppService) : base(repository)
IAssembleIssueJobRepository repository,
IBalanceAppService balanceAppService,
IExpectOutAppService expectOutAppService) : base(repository)
{
_balanceAppService = balanceAppService;
_expectOutAppService = expectOutAppService;
@ -49,7 +51,6 @@ public class AssembleIssueJobManager : SfsJobManagerBase<AssembleIssueJob, Assem
$" 的库存被占用【预计出】");
}
//var balanceDto = await _balanceAppService.GetRealQtyByPackingCodeAndItemCodeAndLocationCodeAndStatusAsync(detail.HandledFromPackingCode, detail.ItemCode, detail.HandledFromLocationCode, detail.Status, detail.HandledFromLot).ConfigureAwait(false);
var balanceDto = await _balanceAppService.GetRealQtyByPackingCodeAndItemCodeAndLocationCodeAndStatusAsync(inputDetail.HandledFromPackingCode, inputDetail.ItemCode, inputDetail.HandledFromLocationCode, inputDetail.Status, inputDetail.HandledFromLot).ConfigureAwait(false);
if (balanceDto.Qty <= 0)
{

8
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Notes/IssueNotes/AssembleIssueNotes/AssembleIssueNote.cs

@ -21,12 +21,9 @@ public class AssembleIssueNote : SfsStoreAggregateRootBase<AssembleIssueNoteDeta
/// <summary>
/// 明细列表
/// </summary>
[IgnoreUpdate]
public override List<AssembleIssueNoteDetail> Details { get; set; } = new List<AssembleIssueNoteDetail>();
[IgnoreUpdate]
public string RequestNumber { get; set; }
/// <summary>
/// 叫料类型
/// </summary>
@ -36,14 +33,12 @@ public class AssembleIssueNote : SfsStoreAggregateRootBase<AssembleIssueNoteDeta
/// <summary>
/// 使用在途库
/// </summary>
[IgnoreUpdate]
public bool UseOnTheWayLocation { get; set; }
/// <summary>
/// 确认时间
/// </summary>
[Display(Name = "确认时间")]
[IgnoreUpdate]
public DateTime? ConfirmTime { get; set; }
/// <summary>
@ -52,6 +47,8 @@ public class AssembleIssueNote : SfsStoreAggregateRootBase<AssembleIssueNoteDeta
[Display(Name = "已确认")]
public bool Confirmed { get; set; }
public EnumIssueSendType EnumIssueSendType { get; set; }
public void Confirm(DateTime confirmTime)
{
@ -68,4 +65,5 @@ public class AssembleIssueNote : SfsStoreAggregateRootBase<AssembleIssueNoteDeta
}
}
}

9
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/IssueRequests/AssembleIssueRequests/AssembleIssueRequest.cs

@ -11,7 +11,7 @@ namespace Win_in.Sfs.Wms.Store.Domain;
public class AssembleIssueRequest : SfsStoreRequestAggregateRootBase<AssembleIssueRequestDetail>
{
/// <summary>
/// 叫料类型
/// 叫料类型
/// </summary>
[Display(Name = "叫料类型")]
public EnumIssueRequestType IssueRequestType { get; set; }
@ -20,10 +20,5 @@ public class AssembleIssueRequest : SfsStoreRequestAggregateRootBase<AssembleIss
/// 使用在途库
/// </summary>
public bool UseOnTheWayLocation { get; set; }
/// <summary>
/// 明细列表
/// </summary>
[IgnoreUpdate]
public override List<AssembleIssueRequestDetail> Details { get; set; } = new List<AssembleIssueRequestDetail>();
}

2
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/IssueRequests/AssembleIssueRequests/AssembleIssueRequestDetail.cs

@ -11,7 +11,6 @@ namespace Win_in.Sfs.Wms.Store.Domain;
/// </summary>
public class AssembleIssueRequestDetail : SfsStoreDetailWithQtyEntityBase, IHasToLocation
{
#region 目标库位信息
/// <summary>
@ -47,6 +46,7 @@ public class AssembleIssueRequestDetail : SfsStoreDetailWithQtyEntityBase, IHasT
#endregion
/// <summary>
/// 生产线
/// </summary>

34
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/IssueRequests/AssembleIssueRequests/AssembleIssueRequestManager.cs

@ -14,29 +14,24 @@ public class AssembleIssueRequestManager
, IAssembleIssueRequestManager
{
private readonly IAssembleIssueRequestRepository _repository;
public AssembleIssueRequestManager(
IAssembleIssueRequestRepository repository
) : base(repository)
) : base(repository)
{
_repository = repository;
}
#region 东阳V2
#endregion
/// <summary>
/// 创建
/// 创建 同时 直接赋值Number 为了返回Number
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
public virtual async Task<AssembleIssueRequest> CreateByNumberAsync(AssembleIssueRequest entity)
{
var number = string.IsNullOrEmpty(entity.Number) ? await GenerateNumberAsync(nameof(AssembleIssueRequest), entity.ActiveDate).ConfigureAwait(false) : entity.Number;
var number = string.IsNullOrEmpty(entity.Number)
? await GenerateNumberAsync(nameof(AssembleIssueRequest), entity.ActiveDate).ConfigureAwait(false)
: entity.Number;
entity.SetIdAndNumberWithDetails(GuidGenerator, number);
entity.Submit();
entity.Agree();
@ -47,7 +42,6 @@ public class AssembleIssueRequestManager
return entity;
}
public virtual async Task CompleteAsync(string number)
{
var entity = await GetByNumberAsync(number).ConfigureAwait(false);
@ -56,23 +50,9 @@ public class AssembleIssueRequestManager
await CompleteAsync(entity).ConfigureAwait(false);
}
}
#region 导入
/// <summary>
/// 执行导入
/// </summary>
public virtual async Task ImportDataAsync(List<AssembleIssueRequest> mergeEntities, List<AssembleIssueRequest> deleteEntities = null)
public Task ImportDataAsync(List<AssembleIssueRequest> entities, List<AssembleIssueRequest> deleteEntities = null)
{
if (deleteEntities != null && deleteEntities.Count > 0)
{
await _repository.BulkDeleteAsync(deleteEntities).ConfigureAwait(false);
}
await CreateManyAsync(mergeEntities).ConfigureAwait(false);
throw new System.NotImplementedException();
}
#endregion
}

4
be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Requests/IssueRequests/AssembleIssueRequests/AssembleIssueRequestDbContextModelCreatingExtensions.cs

@ -43,8 +43,8 @@ public static class AssembleIssueRequestDbContextModelCreatingExtensions
b.Property(q => q.ToLocationErpCode).IsRequired().HasMaxLength(SfsPropertyConst.CodeLength);
b.Property(q => q.ToWarehouseCode).IsRequired().HasMaxLength(SfsPropertyConst.CodeLength);
b.Property(q => q.ToLocationArea).IsRequired().HasMaxLength(SfsPropertyConst.CodeLength);
b.Property(q => q.ToLocationGroup).IsRequired().HasMaxLength(SfsPropertyConst.CodeLength);
b.Property(q => q.ProdLine).HasMaxLength(SfsPropertyConst.CodeLength);
b.Property(q => q.ToLocationGroup).IsRequired().HasMaxLength(SfsPropertyConst.CodeLength);
b.Property(q => q.ProdLine).HasMaxLength(SfsPropertyConst.CodeLength);
b.Property(q => q.IssuedQty).HasPrecision(18, 6);
b.Property(q => q.ReceivedQty).HasPrecision(18, 6);
b.Property(q => q.Status).HasMaxLength(SfsPropertyConst.NameLength).HasConversion<string>();

9
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/AutoMapperProfiles/Jobs/AssembleJobAutoMapperProfile.cs

@ -33,5 +33,14 @@ public partial class StoreEventAutoMapperProfile : Profile
;
CreateMap<AssembleIssueJobDetail, AssembleIssueNoteDetailInput>()
;
CreateMap<AssembleIssueJobDTO, AssembleIssueNoteEditInput>()
.ForMember(x => x.RequestNumber, y => y.MapFrom(d => d.AssembleRequestNumber))
.Ignore(x => x.Confirmed)
.Ignore(x => x.JobNumber)
.Ignore(x => x.ActiveDate)
;
CreateMap<AssembleIssueJobDetailDTO, AssembleIssueNoteDetailInput>()
;
}
}

1
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/AutoMapperProfiles/Notes/AssembleNoteAutoMapperProfile.cs

@ -48,5 +48,4 @@ public partial class StoreEventAutoMapperProfile : Profile
;
}
}

39
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/AutoMapperProfiles/Requests/AssembleIssueRequestAutoMapperProfile.cs

@ -12,25 +12,26 @@ public partial class StoreEventAutoMapperProfile : Profile
private void AssembleIssueRequestAutoMapperProfile()
{
CreateMap<AssembleIssueRequest, AssembleIssueJobEditInput>()
.ForMember(x => x.AssembleRequestNumber, y => y.MapFrom(d => d.Number))
.Ignore(x => x.WarehouseCode)
.Ignore(x => x.UpStreamJobNumber)
.Ignore(x => x.JobType)
.Ignore(x => x.IsAutoComplete)
.Ignore(x => x.ExpiredTime)
.Ignore(x => x.JobDescription)
.Ignore(x => x.JobStatus)
.Ignore(x => x.WorkGroupCode)
.Ignore(x => x.Priority)
.Ignore(x => x.PriorityIncrement)
.Ignore(x => x.AcceptUserId)
.Ignore(x => x.AcceptTime)
.Ignore(x => x.AcceptUserName)
.Ignore(x => x.CompleteUserId)
.Ignore(x => x.CompleteUserName)
.Ignore(x => x.CompleteTime)
.Ignore(x => x.Details)
;
.ForMember(x => x.AssembleRequestNumber, y => y.MapFrom(d => d.Number))
.Ignore(x => x.WarehouseCode)
.Ignore(x => x.UpStreamJobNumber)
.Ignore(x => x.JobType)
.Ignore(x => x.IsAutoComplete)
.Ignore(x => x.ExpiredTime)
.Ignore(x => x.JobDescription)
.Ignore(x => x.JobStatus)
.Ignore(x => x.WorkGroupCode)
.Ignore(x => x.Priority)
.Ignore(x => x.PriorityIncrement)
.Ignore(x => x.AcceptUserId)
.Ignore(x => x.AcceptTime)
.Ignore(x => x.AcceptUserName)
.Ignore(x => x.CompleteUserId)
.Ignore(x => x.CompleteUserName)
.Ignore(x => x.CompleteTime)
.Ignore(x => x.Details)
.Ignore(x => x.EnumIssueSendType)
;
}
}

146
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/Jobs/AssembleIssueJobEventHandler.cs

@ -1,6 +1,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Castle.Components.DictionaryAdapter;
using Volo.Abp.EventBus;
using Volo.Abp.Uow;
using Win_in.Sfs.Basedata.Application.Contracts;
@ -18,16 +19,16 @@ public class AssembleIssueJobEventHandler :
, ILocalEventHandler<SfsCreatedEntityEventData<AssembleIssueJob>>
, ILocalEventHandler<SfsCreatedEntityEventData<List<AssembleIssueJob>>>
{
private readonly IAssembleIssueNoteAppService _assembleNoteAppService;
private readonly IAssembleIssueNoteAppService _assembleIssueNoteAppService;
private readonly IExpectOutAppService _expectOutAppService;
private readonly ILocationAppService _locationAppService;
private readonly ITransferLibRequestAppService _transferLibRequestAppService;
public AssembleIssueJobEventHandler(IAssembleIssueNoteAppService assembleNoteAppService,
public AssembleIssueJobEventHandler(IAssembleIssueNoteAppService assembleIssueNoteAppService,
IExpectOutAppService expectOutAppService,
ILocationAppService locationAppService, ITransferLibRequestAppService transferLibRequestAppService)
{
_assembleNoteAppService = assembleNoteAppService;
_assembleIssueNoteAppService = assembleIssueNoteAppService;
_expectOutAppService = expectOutAppService;
_locationAppService = locationAppService;
_transferLibRequestAppService = transferLibRequestAppService;
@ -41,9 +42,7 @@ public class AssembleIssueJobEventHandler :
[UnitOfWork]
public virtual async Task HandleEventAsync(SfsCompletedEntityEventData<AssembleIssueJob> eventData)
{
var entity = eventData.Entity;
var assembleNote = await BuildAssembleIssueNoteAsync(entity).ConfigureAwait(false);
await _assembleNoteAppService.CreateAsync(assembleNote).ConfigureAwait(false);
await Task.CompletedTask.ConfigureAwait(false);
}
/// <summary>
@ -123,65 +122,72 @@ public class AssembleIssueJobEventHandler :
/// 根据是否在 第一层 来创建 是否生成库移任务
/// </summary>
/// <returns></returns>
private async Task CreateTransferLibAsync(AssembleIssueJob assembleJob)
private async Task CreateTransferLibAsync(AssembleIssueJob assembleIssueJob)
{
if (!await IsMinRowAsync(assembleJob).ConfigureAwait(false))
foreach (var detail in assembleIssueJob.Details)
{
foreach (var detail in assembleJob.Details)
var locationDto = await _locationAppService.GetByCodeAsync(detail.RecommendFromLocationCode)
.ConfigureAwait(false);
if (locationDto.Type == EnumLocationType.RAW)
{
var input = new TransferLibRequestEditInput();
input.CallBusinessType = nameof(IAssembleIssueJobAppService);
input.CallJobNumber = assembleJob.Number;
input.CallRequestNumber = assembleJob.AssembleRequestNumber;
input.CallServerName = "Win_in.Sfs.Wms.Store.Application.AssembleIssueJobAppService";
input.Type = "Transfer_Warehouse";
input.UseOnTheWayLocation = true;
var detailInput = new TransferLibRequestDetailInput();
detailInput.CallBusinessType = nameof(IAssembleIssueJobAppService);
detailInput.CallRequestNumber = assembleJob.AssembleRequestNumber;
detailInput.CallServerName = "Win_in.Sfs.Wms.Store.Application.AssembleIssueJobAppService";
detailInput.CallJobNumber = assembleJob.Number;
detailInput.JobStatus = EnumJobStatus.Open;
detailInput.ItemCode = detail.ItemCode;
detailInput.StdPackQty = detail.StdPackQty;
detailInput.Uom = detail.Uom;
detailInput.Status = detail.Status;
detailInput.RecommendFromQty = detail.RecommendFromQty;
detailInput.RecommendFromLot = detail.RecommendFromLot;
detailInput.RecommendFromPackingCode = detailInput.RecommendFromPackingCode;
detailInput.RecommendToLot = detail.RecommendToLot;
detailInput.RecommendFromArriveDate = detail.RecommendFromArriveDate;
detailInput.RecommendFromExpireDate = detail.RecommendFromExpireDate;
detailInput.RecommendFromProduceDate = detail.RecommendFromProduceDate;
detailInput.RecommendFromSupplierBatch = detail.RecommendFromSupplierBatch;
detailInput.RecommendFromLocationCode = detail.RecommendFromLocationCode;
detailInput.RecommendFromLocationGroup = detail.RecommendFromLocationGroup;
detailInput.RecommendFromLocationArea = detail.RecommendFromLocationArea;
detailInput.RecommendFromLocationErpCode = detail.RecommendFromLocationErpCode;
detailInput.RecommendFromWarehouseCode = detail.RecommendFromWarehouseCode;
detailInput.RecommendToQty = detail.RecommendToQty;
detailInput.RecommendToLot = detail.RecommendToLot;
detailInput.RecommendToPackingCode = detailInput.RecommendToPackingCode;
detailInput.RecommendToLot = detail.RecommendToLot;
detailInput.RecommendToArriveDate = detail.RecommendToArriveDate;
detailInput.RecommendToExpireDate = detail.RecommendToExpireDate;
detailInput.RecommendToProduceDate = detail.RecommendToProduceDate;
detailInput.RecommendToSupplierBatch = detail.RecommendToSupplierBatch;
detailInput.RecommendToLocationCode = detail.RecommendToLocationCode;
detailInput.RecommendToLocationGroup = detail.RecommendToLocationGroup;
detailInput.RecommendToLocationArea = detail.RecommendToLocationArea;
detailInput.RecommendToLocationErpCode = detail.RecommendToLocationErpCode;
detailInput.RecommendToWarehouseCode = detail.RecommendToWarehouseCode;
await _transferLibRequestAppService.CreateAsync(input).ConfigureAwait(false);
if (!await IsMinRowAsync(assembleIssueJob).ConfigureAwait(false))
{
var input = new TransferLibRequestEditInput();
input.CallBusinessType = nameof(IAssembleIssueJobAppService);
input.CallJobNumber = assembleIssueJob.Number;
input.CallRequestNumber = assembleIssueJob.AssembleRequestNumber;
input.CallServerName = "Win_in.Sfs.Wms.Store.Application.AssembleIssueJobAppService";
input.Type = "Transfer_Warehouse";
input.UseOnTheWayLocation = true;
var detailInput = new TransferLibRequestDetailInput();
detailInput.CallBusinessType = nameof(IAssembleIssueJobAppService);
detailInput.CallRequestNumber = assembleIssueJob.AssembleRequestNumber;
detailInput.CallServerName = "Win_in.Sfs.Wms.Store.Application.AssembleIssueJobAppService";
detailInput.CallJobNumber = assembleIssueJob.Number;
detailInput.JobStatus = EnumJobStatus.Open;
detailInput.ItemCode = detail.ItemCode;
detailInput.StdPackQty = detail.StdPackQty;
detailInput.Uom = detail.Uom;
detailInput.Status = detail.Status;
detailInput.RecommendFromQty = detail.RecommendFromQty;
detailInput.RecommendFromLot = detail.RecommendFromLot;
detailInput.RecommendFromPackingCode = detailInput.RecommendFromPackingCode;
detailInput.RecommendToLot = detail.RecommendToLot;
detailInput.RecommendFromArriveDate = detail.RecommendFromArriveDate;
detailInput.RecommendFromExpireDate = detail.RecommendFromExpireDate;
detailInput.RecommendFromProduceDate = detail.RecommendFromProduceDate;
detailInput.RecommendFromSupplierBatch = detail.RecommendFromSupplierBatch;
detailInput.RecommendFromLocationCode = detail.RecommendFromLocationCode;
detailInput.RecommendFromLocationGroup = detail.RecommendFromLocationGroup;
detailInput.RecommendFromLocationArea = detail.RecommendFromLocationArea;
detailInput.RecommendFromLocationErpCode = detail.RecommendFromLocationErpCode;
detailInput.RecommendFromWarehouseCode = detail.RecommendFromWarehouseCode;
detailInput.RecommendToQty = detail.RecommendToQty;
detailInput.RecommendToLot = detail.RecommendToLot;
detailInput.RecommendToPackingCode = detailInput.RecommendToPackingCode;
detailInput.RecommendToLot = detail.RecommendToLot;
detailInput.RecommendToArriveDate = detail.RecommendToArriveDate;
detailInput.RecommendToExpireDate = detail.RecommendToExpireDate;
detailInput.RecommendToProduceDate = detail.RecommendToProduceDate;
detailInput.RecommendToSupplierBatch = detail.RecommendToSupplierBatch;
detailInput.RecommendToLocationCode = detail.RecommendToLocationCode;
detailInput.RecommendToLocationGroup = detail.RecommendToLocationGroup;
detailInput.RecommendToLocationArea = detail.RecommendToLocationArea;
detailInput.RecommendToLocationErpCode = detail.RecommendToLocationErpCode;
detailInput.RecommendToWarehouseCode = detail.RecommendToWarehouseCode;
input.Details = new EditableList<TransferLibRequestDetailInput>() { detailInput };
await _transferLibRequestAppService.CreateAsync(input).ConfigureAwait(false);
}
}
}
}
@ -193,26 +199,26 @@ public class AssembleIssueJobEventHandler :
/// <returns></returns>
private async Task<AssembleIssueNoteEditInput> BuildAssembleIssueNoteAsync(AssembleIssueJob entity)
{
var assembleNoteCreateInput = ObjectMapper.Map<AssembleIssueJob, AssembleIssueNoteEditInput>(entity);
assembleNoteCreateInput.JobNumber = entity.Number;
var assembleIssueNoteCreateInput = ObjectMapper.Map<AssembleIssueJob, AssembleIssueNoteEditInput>(entity);
assembleIssueNoteCreateInput.JobNumber = entity.Number;
await Task.CompletedTask.ConfigureAwait(false);
return assembleNoteCreateInput;
return assembleIssueNoteCreateInput;
}
/// <summary>
/// 判断是不是在最底层 如果不是则把状态变更为等待
/// </summary>
/// <param name="assembleJob"></param>
/// <param name="assembleIssueJob"></param>
/// <returns></returns>
private async Task<bool> IsMinRowAsync(AssembleIssueJob assembleJob)
private async Task<bool> IsMinRowAsync(AssembleIssueJob assembleIssueJob)
{
var detail = assembleJob.Details.FirstOrDefault();
var detail = assembleIssueJob.Details.FirstOrDefault();
var loctionDto = await _locationAppService.GetByCodeAsync(detail.RecommendFromLocationCode)
var locationDto = await _locationAppService.GetByCodeAsync(detail.RecommendFromLocationCode)
.ConfigureAwait(false);
if (loctionDto.RowCode == 1)
if (locationDto.Type == EnumLocationType.RAW && locationDto.RowCode == 1)
{
return true;
}

692
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/Requests/AssembleIssueRequestEventHandler.cs

@ -3,8 +3,10 @@ using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using AutoMapper;
using Castle.Components.DictionaryAdapter;
using Volo.Abp;
using Volo.Abp.AutoMapper;
using Volo.Abp.EventBus;
using Win_in.Sfs.Basedata.Application.Contracts;
using Win_in.Sfs.Shared.Domain.Shared;
@ -25,22 +27,27 @@ public class AssembleIssueRequestEventHandler
, ILocalEventHandler<SfsCreatedEntityEventData<AssembleIssueRequest>>
, ILocalEventHandler<SfsCreatedEntityEventData<List<AssembleIssueRequest>>>
{
private readonly IAssembleIssueJobAppService _assembleJobAppService;
private readonly IAssembleIssueJobAppService _assembleIssueJobAppService;
private readonly IProductionLineAppService _productionLineAppService;
private readonly IProductionLineItemAppService _productionLineItemAppService;
private readonly ILocationAppService _locationAppService;
private readonly IBalanceAppService _balanceAppService;
private IMapper _mapper;
//private readonly IAssembleIssueRequestManager _assembleIssueRequestManager;
public AssembleIssueRequestEventHandler(
IAssembleIssueJobAppService assembleJobAppService, IProductionLineAppService productionLineAppService,
IAssembleIssueJobAppService assembleIssueJobAppService, IProductionLineAppService productionLineAppService,
ILocationAppService locationAppService,
IBalanceAppService balanceAppService, IProductionLineItemAppService productionLineItemAppService)
IBalanceAppService balanceAppService, IProductionLineItemAppService productionLineItemAppService
//, IAssembleIssueRequestManager assembleIssueRequestManager
)
{
_assembleJobAppService = assembleJobAppService;
_assembleIssueJobAppService = assembleIssueJobAppService;
_productionLineAppService = productionLineAppService;
_locationAppService = locationAppService;
_balanceAppService = balanceAppService;
_productionLineItemAppService = productionLineItemAppService;
//_assembleIssueRequestManager = assembleIssueRequestManager;
}
/// <summary>
@ -49,7 +56,9 @@ public class AssembleIssueRequestEventHandler
/// <param name="eventData">Event data</param>
public virtual async Task HandleEventAsync(SfsCreatedEntityEventData<AssembleIssueRequest> eventData)
{
await Task.CompletedTask.ConfigureAwait(false);
var entity = eventData.Entity;
await CreateAllAssembleIssueJobAsync(entity).ConfigureAwait(false);
}
/// <summary>
@ -58,6 +67,8 @@ public class AssembleIssueRequestEventHandler
/// <param name="eventData">Event data</param>
public virtual async Task HandleEventAsync(SfsCreatedEntityEventData<List<AssembleIssueRequest>> eventData)
{
var entity = eventData.Entity;
await Task.CompletedTask.ConfigureAwait(false);
}
@ -70,22 +81,7 @@ public class AssembleIssueRequestEventHandler
{
var entity = eventData.Entity;
List<AssembleIssueJobEditInput> assembleJobs = new EditableList<AssembleIssueJobEditInput>();
//switch (entity.Type)
//{
// case nameof(EnumIssueType.BoxQty):
// assembleJobs = await CreateAssembleIssueJobWithBoxQtyTypeAsync(entity).ConfigureAwait(false);
// break;
// case nameof(EnumIssueType.Qty):
// assembleJobs = await CreateAssembleIssueJobWithQtyTypeAsync(entity).ConfigureAwait(false);
// break;
//}
if (assembleJobs.Any())
{
await _assembleJobAppService.CreateManyAsync(assembleJobs).ConfigureAwait(false);
}
await CreateAllAssembleIssueJobAsync(entity).ConfigureAwait(false);
}
/// <summary>
@ -106,7 +102,7 @@ public class AssembleIssueRequestEventHandler
public virtual async Task HandleEventAsync(SfsCompletedEntityEventData<AssembleIssueRequest> eventData)
{
_ = eventData.Entity;
// await _assembleJobAppService.CompleteByAssembleIssueRequestAsync(entity.Number);
// await _assembleIssueJobAppService.CompleteByAssembleIssueRequestAsync(entity.Number);
await Task.CompletedTask.ConfigureAwait(false);
}
@ -116,194 +112,135 @@ public class AssembleIssueRequestEventHandler
#region 按数量叫料
/// <summary>
/// 创建注塑任务
/// 创建注塑任务-按数量
/// </summary>
/// <param name="assembleRequest"></param>
/// <param name="assembleIssueRequest"></param>
/// <param name="assembleIssueRequestDetails"></param>
/// <param name="recommendbalanceDtos"></param>
/// <param name="useBalanceList"></param>
/// <returns></returns>
/// <exception cref="UserFriendlyException"></exception>
private async Task<List<AssembleIssueJobEditInput>> CreateAssembleIssueJobWithQtyTypeAsync
(AssembleIssueRequest assembleRequest)
(AssembleIssueRequest assembleIssueRequest, List<AssembleIssueRequestDetail> assembleIssueRequestDetails,
List<BalanceDTO> recommendbalanceDtos,
List<BalanceDTO> useBalanceList)
{
var jobs = new List<AssembleIssueJobEditInput>();
//用来临时存放所有未生成任务的发料集合 如果生成完了再这里去掉
var tempDetailDtos =
ObjectMapper.Map<List<AssembleIssueRequestDetail>, List<AssembleIssueRequestDetailDTO>>(
assembleIssueRequestDetails);
var toLocationCodes = assembleRequest.Details.Select(p => p.ToLocationCode).Distinct().ToList(); //所有发送库位的集合
var toLocations = await _locationAppService.GetByCodesAsync(toLocationCodes).ConfigureAwait(false); //所有库位的集合
var assembleIssueJobDetailInputs = new List<AssembleIssueJobDetailInput>();
var assembleRequestDetails = assembleRequest.Details.Where(p => p.ToBeIssuedQty > 0); //所有还没发送物品的集合
foreach (var assembleRequestDetail in assembleRequestDetails) //如果有还有剩余未叫料的数量 则创建新的任务
if (recommendbalanceDtos != null && recommendbalanceDtos.Count > 0)
{
var toLocation =
toLocations.FirstOrDefault(p => p.Code == assembleRequestDetail.ToLocationCode); //判断目标库位是否存在
Check.NotNull(toLocation, "库位代码", $"库位 {assembleRequestDetail.ToLocationCode} 不存在");
//创建详情
var jobDetails =
await CreateAssembleIssueJobDetailInputsWithQtyTypeAsync(assembleRequest, assembleRequestDetail,
toLocation.LocationGroupCode).ConfigureAwait(false);
if (!jobDetails.Any())
var queue = new Queue<BalanceDTO>(recommendbalanceDtos);
while (queue.TryDequeue(out var balanceDto))
{
continue;
}
var next = false;
var fromLocationCode = jobDetails[0].RecommendFromLocationCode;
var fromLocation = await _locationAppService.GetByCodeAsync(fromLocationCode).ConfigureAwait(false);
var job = jobs.FirstOrDefault(p => p.WorkGroupCode == fromLocation?.WorkGroupCode);
if (job == null || job.Details.Any(p => p.RecommendToLocationCode != assembleRequestDetail.ToLocationCode))
{
job = await BuildAssembleIssueJobCreateInputWithQtyTypeAsync(assembleRequest, fromLocation)
.ConfigureAwait(false);
jobs.Add(job);
}
var temp = tempDetailDtos.ToList();
job.Details.AddRange(jobDetails);
if (assembleRequestDetail.ToBeIssuedQty < 0)
{
assembleRequestDetail.Status = EnumStatus.Close;
}
}
jobs = jobs.Where(p => p.Details.Any()).ToList();
foreach (var tempDetailDto in tempDetailDtos)
{
//未发送的数量
tempDetailDto.Qty = tempDetailDto.Qty - tempDetailDto.IssuedQty;
if (tempDetailDto.Qty > balanceDto.Qty) //需求量大于 这条推荐库存的余额
{
tempDetailDto.Qty -= balanceDto.Qty;
}
else if (tempDetailDto.Qty <= balanceDto.Qty)
{
temp.Remove(tempDetailDto);
balanceDto.Qty = tempDetailDto.Qty;
}
assembleIssueJobDetailInputs.Add(
await BuildAssembleIssueJobDetailWithQtyTypeAsync(tempDetailDto, balanceDto)
.ConfigureAwait(false));
useBalanceList.Add(balanceDto);
if (balanceDto.Qty <= 0)
{
next = true;
break;
}
}
var openRequestDetails =
assembleRequest.Details.Where(p => p.Status != EnumStatus.Close).ToList();
tempDetailDtos = temp;
if (!openRequestDetails.Any())
{
return jobs;
if (next)
{
}
}
}
var enableMultipleCreateAssembleIssueJob = await SettingManager
.IsTrueAsync(StoreSettings.MaterialRequest.EnableMultipleCreateIssueJob).ConfigureAwait(false);
if (enableMultipleCreateAssembleIssueJob)
if (assembleIssueJobDetailInputs.Any())
{
//assembleRequest.Partial();
}
else
{
var sb = new StringBuilder();
foreach (var openRequestDetail in openRequestDetails)
{
sb.AppendLine(
$"{openRequestDetail.ItemCode}请求数量 {openRequestDetail.Qty},可用库存数量 {openRequestDetail.IssuedQty}");
}
throw new UserFriendlyException($"{sb} 可用库存数量不足, 无法生成发料任务");
var assembleIssueJobEditInput = new AssembleIssueJobEditInput();
assembleIssueJobEditInput = await BuildAssembleIssueJobCreateInputWithQtyTypeAsync(assembleIssueRequest,
assembleIssueRequestDetails.First()).ConfigureAwait(false);
assembleIssueJobEditInput.Details = assembleIssueJobDetailInputs;
jobs.Add(assembleIssueJobEditInput);
}
return jobs;
}
/// <summary>
/// 构造注塑任务
/// 构造注塑任务-按数量
/// </summary>
/// <param name="assembleRequest"></param>
/// <param name="fromLocation"></param>
/// <param name="assembleIssueRequest"></param>
/// <param name="requestDetailInput"></param>
/// <returns></returns>
private async Task<AssembleIssueJobEditInput> BuildAssembleIssueJobCreateInputWithQtyTypeAsync(
AssembleIssueRequest assembleRequest,
LocationDTO fromLocation)
AssembleIssueRequest assembleIssueRequest, AssembleIssueRequestDetail requestDetailInput)
{
AssembleIssueJobEditInput job;
job = ObjectMapper.Map<AssembleIssueRequest, AssembleIssueJobEditInput>(assembleRequest);
var job = ObjectMapper.Map<AssembleIssueRequest, AssembleIssueJobEditInput>(assembleIssueRequest);
job.JobType = EnumJobType.IssueJob;
job.JobStatus = EnumJobStatus.Open;
job.WorkGroupCode = fromLocation.WorkGroupCode;
job.WarehouseCode = fromLocation.WarehouseCode;
job.Worker = assembleRequest.Worker;
if (string.IsNullOrEmpty(job.Worker))
{
job.Worker = "admin";
}
job.AssembleRequestNumber = assembleRequest.Number;
job.WorkGroupCode = requestDetailInput.ToLocationGroup;
job.WarehouseCode = requestDetailInput.ToWarehouseCode;
job.Worker = assembleIssueRequest.Worker;
job.AssembleRequestNumber = assembleIssueRequest.Number;
job.EnumIssueSendType = EnumIssueSendType.QtyType;
await Task.CompletedTask.ConfigureAwait(false);
return job;
}
/// <summary>
/// 创建注塑任务明细
/// </summary>
/// <param name="assembleRequest"></param>
/// <param name="assembleRequestDetail"></param>
/// <param name="toLocationGroupCode"></param>
/// <returns></returns>
/// <exception cref="UserFriendlyException"></exception>
private async Task<List<AssembleIssueJobDetailInput>> CreateAssembleIssueJobDetailInputsWithQtyTypeAsync(
AssembleIssueRequest assembleRequest,
AssembleIssueRequestDetail assembleRequestDetail, string toLocationGroupCode)
{
var jobDetails = new List<AssembleIssueJobDetailInput>();
//获取推荐库存
var productionLineDto = await _productionLineAppService
.GetByLocationCodeAsync(assembleRequestDetail.ToLocationCode).ConfigureAwait(false);
var productionLineItemDtos = await _productionLineItemAppService
.GetByProductLineCodeAsync(productionLineDto.Code).ConfigureAwait(false);
if (productionLineItemDtos == null)
{
throw new UserFriendlyException($"物品代码【{assembleRequestDetail.ItemCode}】没有对应的【生产线物品关系】");
}
var productionLineItemDto =
productionLineItemDtos.FirstOrDefault(p => p.ItemCode == assembleRequestDetail.ItemCode);
var input = new RecommendBalanceRequestInput
{
ItemCode = assembleRequestDetail.ItemCode,
Qty = assembleRequestDetail.ToBeIssuedQty,
//LocationTypes = transactionType.OutLocationTypes, productionLineItemDto.RawLocationCodeListJson
Statuses = new EditableList<EnumInventoryStatus> { EnumInventoryStatus.OK },
Locations = JsonSerializer.Deserialize<List<string>>(productionLineItemDto.RawLocationCodeListJson)
};
var recommendList = await _balanceAppService.GetRecommendBalancesByLocationsAsync(input).ConfigureAwait(false);
//没有推荐库存时 跳过此明细 不生成任务
if (recommendList.Count != 0)
{
foreach (var recommend in recommendList)
{
//拿走需求量
var detail =
await BuildAssembleIssueJobDetailWithQtyTypeAsync(assembleRequestDetail, recommend,
toLocationGroupCode)
.ConfigureAwait(false);
if (assembleRequest.UseOnTheWayLocation)
{
//获取在途库
var locationDto = await _locationAppService.GetFirstByTypeAsync(EnumLocationType.TRANSPORT)
.ConfigureAwait(false);
detail.OnTheWayLocationCode = locationDto.Code;
}
jobDetails.Add(detail);
assembleRequestDetail.IssuedQty += recommend.Qty;
//await _assembleRequestManager.UpdateDetailsAsync(assembleRequest).ConfigureAwait(false);
}
}
return jobDetails;
}
/// <summary>
/// 构造注塑任务明细
/// 构造注塑任务明细-按数量
/// </summary>
/// <param name="assembleRequestDetail"></param>
/// <param name="assembleIssueRequestDetail"></param>
/// <param name="balance"></param>
/// <param name="toLocationGroupCode"></param>
/// <returns></returns>
private async Task<AssembleIssueJobDetailInput> BuildAssembleIssueJobDetailWithQtyTypeAsync(
AssembleIssueRequestDetail assembleRequestDetail, BalanceDTO balance, string toLocationGroupCode)
AssembleIssueRequestDetailDTO assembleIssueRequestDetail, BalanceDTO balance)
{
//ProductionLineDTO prodLine = await _productionLineAppService.GetByLocationGroupCodeAsync(toLocationGroupCode).ConfigureAwait(false);
var detail = ObjectMapper.Map<BalanceDTO, AssembleIssueJobDetailInput>(balance);
detail.RequestLocationCode = assembleRequestDetail.ToLocationCode;
detail.PositionCode = assembleRequestDetail.PositionCode;
detail.RecommendType = assembleRequestDetail.RecommendType;
var detail = new AssembleIssueJobDetailInput();
detail.RequestLocationCode = assembleIssueRequestDetail.ToLocationCode;
detail.PositionCode = assembleIssueRequestDetail.PositionCode;
detail.RecommendType = assembleIssueRequestDetail.RecommendType;
detail.Uom = balance.Uom;
detail.ItemCode = balance.ItemCode;
detail.ItemDesc2 = balance.ItemDesc2;
detail.ItemDesc1 = balance.ItemDesc1;
detail.ItemName = balance.ItemName;
detail.ProdLine = assembleIssueRequestDetail.ProdLine;
detail.RequestQty = balance.Qty;
detail.StdPackQty = assembleIssueRequestDetail.StdPackQty;
detail.Status = balance.Status;
detail.RequestLocationErpCode = assembleIssueRequestDetail.ToLocationErpCode;
detail.RequestLocationArea = assembleIssueRequestDetail.ToLocationArea;
detail.RequestWarehouseCode = assembleIssueRequestDetail.ToWarehouseCode;
detail.RequestLocationGroup = assembleIssueRequestDetail.ToLocationGroup;
detail.RequestLocationCode = assembleIssueRequestDetail.ToLocationCode;
detail.RecommendFromPackingCode = balance.PackingCode;
detail.RecommendFromContainerCode = balance.ContainerCode;
@ -313,21 +250,69 @@ public class AssembleIssueRequestEventHandler
detail.RecommendFromLot = balance.Lot;
detail.RecommendFromProduceDate = balance.ProduceDate;
detail.RecommendFromArriveDate = balance.ArriveDate;
detail.RecommendFromQty = balance.Qty;
detail.RecommendFromContainerCode = balance.ContainerCode;
detail.RecommendFromPackingCode = balance.PackingCode;
detail.RecommendToPackingCode = balance.PackingCode;
detail.RecommendToContainerCode = balance.ContainerCode;
detail.RecommendToSupplierBatch = balance.SupplierBatch;
detail.RecommendToProduceDate = balance.ProduceDate;
detail.RecommendToExpireDate = balance.ExpireDate;
detail.RecommendToLot = balance.Lot;
detail.RecommendToProduceDate = balance.ProduceDate;
detail.RecommendToArriveDate = balance.ArriveDate;
detail.RecommendToQty = balance.Qty;
detail.RecommendToContainerCode = balance.ContainerCode;
detail.RecommendToPackingCode = balance.PackingCode;
detail.RecommendFromLocationArea = balance.LocationArea;
detail.RecommendFromLocationCode = balance.LocationCode;
detail.RecommendFromLocationErpCode = balance.LocationErpCode;
detail.RecommendFromLocationGroup = balance.LocationGroup;
detail.RecommendFromWarehouseCode = balance.WarehouseCode;
detail.RecommendFromQty = balance.Qty;
detail.Uom = balance.Uom;
detail.RecommendToLocationCode = assembleRequestDetail.ToLocationCode;
detail.RecommendToLocationErpCode = assembleRequestDetail.ToLocationErpCode;
detail.RecommendToLocationArea = assembleRequestDetail.ToLocationArea;
detail.RecommendToWarehouseCode = assembleRequestDetail.ToWarehouseCode;
detail.RecommendToLocationCode = assembleIssueRequestDetail.ToLocationCode;
detail.RecommendToLocationErpCode = assembleIssueRequestDetail.ToLocationErpCode;
detail.RecommendToLocationArea = assembleIssueRequestDetail.ToLocationArea;
detail.RecommendToWarehouseCode = assembleIssueRequestDetail.ToWarehouseCode;
detail.RecommendToLocationGroup = assembleIssueRequestDetail.ToLocationGroup;
detail.TransferLibFromPackingCode = balance.PackingCode;
detail.TransferLibFromContainerCode = balance.ContainerCode;
detail.TransferLibFromSupplierBatch = balance.SupplierBatch;
detail.TransferLibFromProduceDate = balance.ProduceDate;
detail.TransferLibFromExpireDate = balance.ExpireDate;
detail.TransferLibFromLot = balance.Lot;
detail.TransferLibFromProduceDate = balance.ProduceDate;
detail.TransferLibFromArriveDate = balance.ArriveDate;
detail.TransferLibFromQty = balance.Qty;
detail.TransferLibFromContainerCode = balance.ContainerCode;
detail.TransferLibFromPackingCode = balance.PackingCode;
detail.TransferLibToPackingCode = balance.PackingCode;
detail.TransferLibToContainerCode = balance.ContainerCode;
detail.TransferLibToSupplierBatch = balance.SupplierBatch;
detail.TransferLibToProduceDate = balance.ProduceDate;
detail.TransferLibToExpireDate = balance.ExpireDate;
detail.TransferLibToLot = balance.Lot;
detail.TransferLibToProduceDate = balance.ProduceDate;
detail.TransferLibToArriveDate = balance.ArriveDate;
detail.TransferLibToQty = balance.Qty;
detail.TransferLibToPackingCode = balance.PackingCode;
detail.TransferLibFromLocationArea = balance.LocationArea;
detail.TransferLibFromLocationCode = balance.LocationCode;
detail.TransferLibFromLocationErpCode = balance.LocationErpCode;
detail.TransferLibFromLocationGroup = balance.LocationGroup;
detail.TransferLibFromWarehouseCode = balance.WarehouseCode;
detail.TransferLibToLocationCode = assembleIssueRequestDetail.ToLocationCode;
detail.TransferLibToLocationErpCode = assembleIssueRequestDetail.ToLocationErpCode;
detail.TransferLibToLocationArea = assembleIssueRequestDetail.ToLocationArea;
detail.TransferLibToWarehouseCode = assembleIssueRequestDetail.ToWarehouseCode;
detail.TransferLibToLocationGroup = assembleIssueRequestDetail.ToLocationGroup;
//detail.ProdLine = prodLine == null ? toLocationGroupCode : prodLine.Code;
detail.ProdLine = toLocationGroupCode;
await Task.CompletedTask.ConfigureAwait(false);
return detail;
}
@ -337,72 +322,71 @@ public class AssembleIssueRequestEventHandler
#region 按箱叫料
/// <summary>
/// 创建注塑任务
/// 创建注塑任务 按箱叫料-按箱
/// </summary>
/// <param name="assembleRequest"></param>
/// <param name="assembleIssueRequest"></param>
/// <param name="assembleIssueRequestDetailList"></param>
/// <param name="recommendbalanceDtos"></param>
/// <param name="useBalanceList"></param>
/// <returns></returns>
/// <exception cref="UserFriendlyException"></exception>
private async Task<List<AssembleIssueJobEditInput>> CreateAssembleIssueJobWithBoxQtyTypeAsync
(AssembleIssueRequest assembleRequest)
(
AssembleIssueRequest assembleIssueRequest,
List<AssembleIssueRequestDetail> assembleIssueRequestDetailList,
List<SortBalance> recommendbalanceDtos,
List<BalanceDTO> useBalanceList)
{
var inputJobs = new List<AssembleIssueJobEditInput>();
var inputExpectOutEditInput = new ExpectOutEditInput();
//已用的库存的箱码集合
var useBalanceList = new List<string>();
var groupByItemCodeAndLocationCode =
assembleRequest.Details.GroupBy(p => new { p.ItemCode, p.ToLocationCode });
//已用的库存的集合
useBalanceList = useBalanceList;
foreach (var locationCodeItemCodeGroup in groupByItemCodeAndLocationCode)
foreach (var detail in assembleIssueRequestDetailList)
{
var inputDetails = assembleRequest.Details.Where(p =>
p.ItemCode == locationCodeItemCodeGroup.Key.ItemCode &&
p.ToLocationCode == locationCodeItemCodeGroup.Key.ToLocationCode);
var inputDetailTemplate = inputDetails.First();
//当前零件的集合
var inputDetails = assembleIssueRequestDetailList;
//获取请求下 这个零件和这个库位一个需要多少箱
var sumBoxQty = inputDetails.Sum(p => p.BoxQty);
var sumBoxQty = inputDetails.Sum(p => p.BoxQty - p.IssuedQty);
//获取生产线
var productionLineDto = await _productionLineAppService
.GetByLocationCodeAsync(inputDetails.First().ToLocationCode).ConfigureAwait(false);
if (productionLineDto == null)
{
throw new UserFriendlyException($"库位【{inputDetailTemplate.ToLocationCode}】没有对应的【生产线】");
}
var productLineCodeAndItemCode = await _productionLineItemAppService
.GetByProductLineCodeAndItemCodeAsync(productionLineDto.Code, inputDetailTemplate.ItemCode)
.GetByProductLineCodeAndItemCodeAsync(productionLineDto.Code, detail.ItemCode)
.ConfigureAwait(false);
if (productLineCodeAndItemCode == null)
{
throw new UserFriendlyException(
$"物品代码【{inputDetailTemplate.ItemCode}】在生产线【{productionLineDto.Code}】中没有对应的【生产线物品关系】");
$"物品代码【{detail.ItemCode}】在生产线【{productionLineDto.Code}】中没有对应的【生产线物品关系】");
}
//获取可用库存
var input = new RecommendBalanceRequestInput
{
ItemCode = locationCodeItemCodeGroup.Key.ItemCode,
Qty = decimal.MaxValue,
Statuses = new EditableList<EnumInventoryStatus> { EnumInventoryStatus.OK },
Locations = JsonSerializer.Deserialize<List<string>>(productLineCodeAndItemCode
.RawLocationCodeListJson)
};
var usableList = await _balanceAppService.GetUsableListAsync(input).ConfigureAwait(false);
usableList = usableList.Where(p => !useBalanceList.Contains(p.PackingCode)).ToList();
//可用库存
var usableList = recommendbalanceDtos;
usableList = usableList.Where(p => !useBalanceList.Select(p => p.PackingCode).Contains(p.PackingCode))
.ToList();
if (usableList.Any())
{
for (var i = 0; i < sumBoxQty; i++)
{
var firstUsable = usableList.First();
useBalanceList.Add(firstUsable.PackingCode);
usableList.Remove(firstUsable);
var assembleJobEditInput =
await BuildAssembleIssueJobCreateInputWithBoxQtyTypeAsync(assembleRequest, inputDetailTemplate,
firstUsable)
.ConfigureAwait(false);
inputJobs.Add(assembleJobEditInput);
if (usableList.Any())
{
var firstUsable = usableList.First();
useBalanceList.Add((BalanceDTO)firstUsable);
usableList.Remove(firstUsable);
var assembleIssueJobEditInput =
await BuildAssembleIssueJobCreateInputWithBoxQtyTypeAsync(assembleIssueRequest,
detail, firstUsable)
.ConfigureAwait(false);
inputJobs.Add(assembleIssueJobEditInput);
}
else
{
break;
}
}
}
}
@ -411,25 +395,26 @@ public class AssembleIssueRequestEventHandler
}
/// <summary>
/// 构造注塑任务
/// 构造注塑任务-按箱
/// </summary>
/// <param name="assembleRequest"></param>
/// <param name="assembleRequestDetail"></param>
/// <param name="assembleIssueRequest"></param>
/// <param name="assembleIssueRequestDetail"></param>
/// <param name="balanceDtos"></param>
/// <returns></returns>
private async Task<AssembleIssueJobEditInput> BuildAssembleIssueJobCreateInputWithBoxQtyTypeAsync(
AssembleIssueRequest assembleRequest,
AssembleIssueRequestDetail assembleRequestDetail, BalanceDTO balanceDtos)
AssembleIssueRequest assembleIssueRequest,
AssembleIssueRequestDetail assembleIssueRequestDetail, BalanceDTO balanceDtos)
{
var job = ObjectMapper.Map<AssembleIssueRequest, AssembleIssueJobEditInput>(assembleRequest);
var job = ObjectMapper.Map<AssembleIssueRequest, AssembleIssueJobEditInput>(assembleIssueRequest);
job.JobType = EnumJobType.IssueJob;
job.JobStatus = EnumJobStatus.Open;
job.WorkGroupCode = assembleRequestDetail.ToLocationGroup;
job.WarehouseCode = assembleRequestDetail.ToWarehouseCode;
job.Worker = assembleRequest.Worker;
job.AssembleRequestNumber = assembleRequest.Number;
job.WorkGroupCode = assembleIssueRequestDetail.ToLocationGroup;
job.WarehouseCode = assembleIssueRequestDetail.ToWarehouseCode;
job.Worker = assembleIssueRequest.Worker;
job.AssembleRequestNumber = assembleIssueRequest.Number;
job.EnumIssueSendType = EnumIssueSendType.BoxQtyType;
job.Details.Add(await BuildAssembleIssueJobDetailWithBoxQtyTypeAsync(assembleRequestDetail, balanceDtos)
job.Details.Add(await BuildAssembleIssueJobDetailWithBoxQtyTypeAsync(assembleIssueRequestDetail, balanceDtos)
.ConfigureAwait(false));
await Task.CompletedTask.ConfigureAwait(false);
@ -438,30 +423,31 @@ public class AssembleIssueRequestEventHandler
}
/// <summary>
/// 构造注塑任务明细
/// 构造注塑任务明细-按箱
/// </summary>
/// <param name="assembleRequestDetail"></param>
/// <param name="assembleIssueRequestDetail"></param>
/// <param name="balance"></param>
/// <param name="toLocationGroupCode"></param>
/// <returns></returns>
private async Task<AssembleIssueJobDetailInput> BuildAssembleIssueJobDetailWithBoxQtyTypeAsync(
AssembleIssueRequestDetail assembleRequestDetail, BalanceDTO balance)
AssembleIssueRequestDetail assembleIssueRequestDetail, BalanceDTO balance)
{
var detail = new AssembleIssueJobDetailInput();
detail.RequestLocationCode = assembleRequestDetail.ToLocationCode;
detail.RequestLocationGroup = assembleRequestDetail.ToLocationGroup;
detail.RequestLocationArea = assembleRequestDetail.ToLocationArea;
detail.RequestLocationErpCode = assembleRequestDetail.ToLocationErpCode;
detail.RequestWarehouseCode = assembleRequestDetail.ToWarehouseCode;
detail.PositionCode = assembleRequestDetail.PositionCode;
detail.RecommendType = assembleRequestDetail.RecommendType;
detail.ProdLine = assembleRequestDetail.ToLocationCode;
detail.ItemCode = assembleRequestDetail.ItemCode;
detail.ItemName = assembleRequestDetail.ItemName;
detail.ItemDesc1 = assembleRequestDetail.ItemDesc1;
detail.ItemDesc2 = assembleRequestDetail.ItemDesc2;
detail.RequestLocationCode = assembleIssueRequestDetail.ToLocationCode;
detail.RequestLocationGroup = assembleIssueRequestDetail.ToLocationGroup;
detail.RequestLocationArea = assembleIssueRequestDetail.ToLocationArea;
detail.RequestLocationErpCode = assembleIssueRequestDetail.ToLocationErpCode;
detail.RequestWarehouseCode = assembleIssueRequestDetail.ToWarehouseCode;
detail.RequestQty = 1;
detail.PositionCode = assembleIssueRequestDetail.PositionCode;
detail.RecommendType = assembleIssueRequestDetail.RecommendType;
detail.ProdLine = assembleIssueRequestDetail.ToLocationCode;
detail.ItemCode = assembleIssueRequestDetail.ItemCode;
detail.ItemName = assembleIssueRequestDetail.ItemName;
detail.ItemDesc1 = assembleIssueRequestDetail.ItemDesc1;
detail.ItemDesc2 = assembleIssueRequestDetail.ItemDesc2;
detail.Status = EnumInventoryStatus.OK;
detail.Uom = balance.Uom;
@ -496,11 +482,11 @@ public class AssembleIssueRequestEventHandler
detail.RecommendToProduceDate = balance.ProduceDate;
detail.RecommendToArriveDate = balance.ArriveDate;
detail.RecommendToLocationCode = assembleRequestDetail.ToLocationCode;
detail.RecommendToLocationErpCode = assembleRequestDetail.ToLocationErpCode;
detail.RecommendToLocationArea = assembleRequestDetail.ToLocationArea;
detail.RecommendToWarehouseCode = assembleRequestDetail.ToWarehouseCode;
detail.RecommendToLocationGroup = assembleRequestDetail.ToLocationGroup;
detail.RecommendToLocationCode = assembleIssueRequestDetail.ToLocationCode;
detail.RecommendToLocationErpCode = assembleIssueRequestDetail.ToLocationErpCode;
detail.RecommendToLocationArea = assembleIssueRequestDetail.ToLocationArea;
detail.RecommendToWarehouseCode = assembleIssueRequestDetail.ToWarehouseCode;
detail.RecommendToLocationGroup = assembleIssueRequestDetail.ToLocationGroup;
await Task.CompletedTask.ConfigureAwait(false);
return detail;
@ -509,4 +495,210 @@ public class AssembleIssueRequestEventHandler
#endregion
#endregion
//创建任务
private async Task<List<AssembleIssueJobDTO>> CreateAllAssembleIssueJobAsync(
AssembleIssueRequest assembleIssueRequest)
{
var assembleIssueJobEditInputs = new List<AssembleIssueJobEditInput>();
//已用的库存的集合
var useBalanceList = new List<BalanceDTO>();
foreach (var groupbyItemCodeAndProdLine in assembleIssueRequest.Details.GroupBy(p =>
new { p.ItemCode }))
{
foreach (var assembleIssueRequestDetail in groupbyItemCodeAndProdLine)
{
var productionLineItemDto = await _productionLineItemAppService.GetByProductLineCodeAndItemCodeAsync(
assembleIssueRequestDetail.ProdLine,
groupbyItemCodeAndProdLine.Key.ItemCode).ConfigureAwait(false);
if (productionLineItemDto == null)
{
throw new UserFriendlyException(
$"未在生产线【{assembleIssueRequestDetail.ProdLine}】物品【{groupbyItemCodeAndProdLine.Key.ItemCode}】的关系,请查看【生产线物品关系】");
}
//原料
if (!string.IsNullOrEmpty(productionLineItemDto.RawLocationCodeListJson)) //因为一个零件 要不是原料 要不是半成品
{
var usableLocationCode =
JsonSerializer.Deserialize<List<string>>(productionLineItemDto.RawLocationCodeListJson);
if (usableLocationCode.Any())
{
//获取可用库存
var input = new RecommendBalanceRequestInput
{
ItemCode = assembleIssueRequestDetail.ItemCode,
Qty = decimal.MaxValue,
Statuses = new EditableList<EnumInventoryStatus> { EnumInventoryStatus.OK },
Locations =
JsonSerializer.Deserialize<List<string>>(productionLineItemDto.RawLocationCodeListJson),
IsPackingCode = true
};
var usableList = await _balanceAppService.GetUsableListAsync(input).ConfigureAwait(false);
var sortByFifoAsync = await SortByFifoAsync(usableList).ConfigureAwait(false);
//因为是按箱叫料 先把值赋值给箱数量上
assembleIssueRequestDetail.BoxQty = assembleIssueRequestDetail.Qty;
if (usableList.Any())
{
//因为是原料所以按箱叫料
assembleIssueJobEditInputs.AddRange(
await CreateAssembleIssueJobWithBoxQtyTypeAsync(assembleIssueRequest,
new EditableList<AssembleIssueRequestDetail> { assembleIssueRequestDetail },
sortByFifoAsync,
useBalanceList).ConfigureAwait(false));
}
}
}
//半成品
if (!string.IsNullOrEmpty(productionLineItemDto.ProductLocationCodeListJson)) //因为一个零件 要不是原料 要不是半成品
{
var usableLocationCode =
JsonSerializer.Deserialize<List<string>>(productionLineItemDto.ProductLocationCodeListJson);
if (usableLocationCode.Any())
{
//获取可用库存
var input = new RecommendBalanceRequestInput
{
ItemCode = groupbyItemCodeAndProdLine.Key.ItemCode,
Qty = assembleIssueRequestDetail.Qty,
Statuses = new EditableList<EnumInventoryStatus> { EnumInventoryStatus.OK },
Locations =
JsonSerializer.Deserialize<List<string>>(productionLineItemDto
.ProductLocationCodeListJson),
IsPackingCode = false
};
var usableList = await _balanceAppService.GetUsableListAsync(input).ConfigureAwait(false);
var temp = usableList.ToList();
foreach (var balanceDto in usableList) //计算已经用过的库存
{
var useBalanceDto = useBalanceList.Where(p =>
p.ItemCode == balanceDto.ItemCode && p.LocationCode == balanceDto.LocationCode &&
p.Lot == balanceDto.Lot && p.Status == balanceDto.Status &&
p.PackingCode == balanceDto.PackingCode);
if (useBalanceDto.Any()) //如果不为NULL,就是用过了的库存 需要减去使用量
{
balanceDto.Qty -= useBalanceDto.Sum(p => p.Qty);
if (balanceDto.Qty <= 0)
{
temp.Remove(balanceDto);
}
}
}
usableList = temp;
assembleIssueJobEditInputs.AddRange(
await CreateAssembleIssueJobWithQtyTypeAsync(assembleIssueRequest,
new List<AssembleIssueRequestDetail> { assembleIssueRequestDetail }, temp,
useBalanceList).ConfigureAwait(false));
}
}
}
}
if (assembleIssueJobEditInputs.Count > 0) //有库存 可以创建任务
{
//新增任务
var addAssembleIssueJobDtos = await _assembleIssueJobAppService.CreateManyAsync(assembleIssueJobEditInputs)
.ConfigureAwait(false);
await UpdateAssembleIssueRequestDetailQtyAsync(assembleIssueRequest, addAssembleIssueJobDtos)
.ConfigureAwait(false);
return addAssembleIssueJobDtos;
}
return new List<AssembleIssueJobDTO>();
}
/// <summary>
/// 修改请求的 已发 已收数量
/// </summary>
/// <param name="assembleIssueRequest"></param>
/// <param name="addAssembleIssueJobDtos"></param>
/// <returns></returns>
private async Task UpdateAssembleIssueRequestDetailQtyAsync(AssembleIssueRequest assembleIssueRequest,
List<AssembleIssueJobDTO> addAssembleIssueJobDtos)
{
//原有任务
var existAssembleIssueJobDtos = await _assembleIssueJobAppService
.GetByRequestNumberAsync(assembleIssueRequest.Number)
.ConfigureAwait(false);
//新增的任务和已有的任务总和
var allAssembleIssueJobDtos = new List<AssembleIssueJobDTO>();
allAssembleIssueJobDtos.AddRange(addAssembleIssueJobDtos);
allAssembleIssueJobDtos.AddRange(existAssembleIssueJobDtos);
var groupByItemCodeLocationCode = assembleIssueRequest.Details.GroupBy(p =>
new { p.ItemCode, p.ToLocationCode });
foreach (var group in groupByItemCodeLocationCode)
{
foreach (var requestDetail in group)
{
//所有已发数量
decimal allIssuedQty = 0;
//所有已发数量
decimal allReceivedQty = 0;
foreach (var allAssembleIssueJobDto in allAssembleIssueJobDtos)
{
var jobDetailDtos = allAssembleIssueJobDto.Details.Where(p =>
p.ItemCode == group.Key.ItemCode && p.RequestLocationCode == group.Key.ToLocationCode);
//所有已发数量
allIssuedQty += jobDetailDtos.Sum(p => p.RequestQty);
//所有已发数量
allReceivedQty += jobDetailDtos.Sum(p => p.HandledToQty);
}
requestDetail.IssuedQty += allIssuedQty;
requestDetail.ReceivedQty += allReceivedQty;
}
}
//await _assembleIssueRequestManager.UpdateAsync(assembleIssueRequest).ConfigureAwait(false);
}
/// <summary>
/// 排序规则 1.批次正序 2.底层 3.到货日期正序 4.数量倒序(整箱优先) 5.库位正序 6.箱码正序
/// </summary>
/// <param name="balances"></param>
/// <returns></returns>
public async Task<List<SortBalance>> SortByFifoAsync(List<BalanceDTO> balances)
{
var sortBalances = new List<SortBalance>();
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<BalanceDTO, SortBalance>()
.Ignore(x => x.LocationRow);
});
_mapper = new Mapper(config);
var resultBalances = _mapper.Map<List<BalanceDTO>, List<SortBalance>>(balances);
foreach (var resultBalance in resultBalances)
{
var locationDto = await _locationAppService.GetByCodeAsync(resultBalance.LocationCode).ConfigureAwait(false);
resultBalance.LocationRow = locationDto.RowCode;
}
resultBalances
.OrderBy(p => p.Lot)
.ThenBy(p => p.LocationRow)
.ThenBy(p => p.PutInTime)
.ThenBy(p => p.Qty)//2023-9-14 苑静雯 从小数开始发料
.ThenBy(p => p.LocationCode)
.ThenBy(p => p.PackingCode)
.ToList();
return resultBalances;
}
}

Loading…
Cancel
Save