Browse Source

增加注塑申请、任务、记录

dev_DY_CC
周红军 1 year ago
parent
commit
b5b87bcfd4
  1. 46
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/InjectionJobs/DTOs/InjectionJobDTO.cs
  2. 112
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/InjectionJobs/DTOs/InjectionJobDetailDTO.cs
  3. 26
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/InjectionJobs/IInjectionJobAppService.cs
  4. 27
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/InjectionJobs/InjectionJobPermissions.cs
  5. 6
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/InjectionJobs/Inputs/InjectionJobCheckInput.cs
  6. 134
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/InjectionJobs/Inputs/InjectionJobDetailInput.cs
  7. 82
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/InjectionJobs/Inputs/InjectionJobEditInput.cs
  8. 54
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/InjectionNotes/DTOs/InjectionNoteDTO.cs
  9. 42
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/InjectionNotes/DTOs/InjectionNoteDetailDTO.cs
  10. 21
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/InjectionNotes/IInjectionNoteAppService.cs
  11. 30
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/InjectionNotes/InjectionNotePermissions.cs
  12. 53
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/InjectionNotes/Inputs/InjectionNoteDetailInput.cs
  13. 63
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/InjectionNotes/Inputs/InjectionNoteEditInput.cs
  14. 33
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/InjectionNotes/Inputs/InjectionNoteImportInput.cs
  15. 3
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Permissions/StorePermissionDefinitionProvider.cs
  16. 37
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/InjectionRequests/DTOs/InjectionRequestDTO.cs
  17. 94
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/InjectionRequests/DTOs/InjectionRequestDetailDTO.cs
  18. 35
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/InjectionRequests/IInjectionRequestAppService.cs
  19. 27
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/InjectionRequests/InjectionRequestPermissions.cs
  20. 85
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/InjectionRequests/Inputs/InjectionRequestDetailInput.cs
  21. 58
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/InjectionRequests/Inputs/InjectionRequestEditInput.cs
  22. 53
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/InjectionRequests/Inputs/InjectionRequestImportInput.cs
  23. 144
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Jobs/InjectionJobs/InjectionJobAppService.cs
  24. 30
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Jobs/InjectionJobs/InjectionJobAutoMapperProfile.cs
  25. 108
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Notes/InjectionNotes/InjectionNoteAppService.cs
  26. 31
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Notes/InjectionNotes/InjectionNoteAutoMapperProfile.cs
  27. 2
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Notes/ProductRecycleNotes/ProductRecycleNoteAutoMapperProfile.cs
  28. 503
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Requests/InjectionRequests/InjectionRequestAppService.cs
  29. 74
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Requests/InjectionRequests/InjectionRequestAutoMapperProfile.cs
  30. 2
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/StoreApplicationAutoMapperProfile.cs
  31. 6
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain.Shared/Settings/StoreSettings.cs
  32. 10
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/InjectionJobs/IInjectionJobManager.cs
  33. 6
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/InjectionJobs/IInjectionJobRepository.cs
  34. 84
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/InjectionJobs/InjectionJob.cs
  35. 108
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/InjectionJobs/InjectionJobDetail.cs
  36. 82
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/InjectionJobs/InjectionJobManager.cs
  37. 2
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/IssueJobs/IIssueJobRepository.cs
  38. 10
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Notes/InjectionNotes/IInjectionNoteManager.cs
  39. 6
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Notes/InjectionNotes/IInjectionNoteRepository.cs
  40. 77
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Notes/InjectionNotes/InjectionNote.cs
  41. 43
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Notes/InjectionNotes/InjectionNoteDetail.cs
  42. 42
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Notes/InjectionNotes/InjectionNoteManager.cs
  43. 16
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/InjectionRequests/IInjectionRequestManager.cs
  44. 9
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/InjectionRequests/IInjectionRequestRepository.cs
  45. 47
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/InjectionRequests/InjectionRequest.cs
  46. 105
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/InjectionRequests/InjectionRequestDetail.cs
  47. 141
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/InjectionRequests/InjectionRequestManager.cs
  48. 3
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/IStoreDbContext.cs
  49. 69
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Jobs/InjectionJobs/InjectionJobDbContextModelCreatingExtensions.cs
  50. 11
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Jobs/InjectionJobs/InjectionJobEfCoreRepository.cs
  51. 63
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Notes/InjectionNotes/InjectionNoteDbContextModelCreatingExtensions.cs
  52. 11
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Notes/InjectionNotes/InjectionNoteEfCoreRepository.cs
  53. 67
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Requests/InjectionRequests/InjectionRequestDbContextModelCreatingExtensions.cs
  54. 11
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Requests/InjectionRequests/InjectionRequestEfCoreRepository.cs
  55. 3
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/StoreDbContext.cs
  56. 3
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/StoreDbContextModelCreatingExtensions.cs
  57. 9
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/StoreEntityFrameworkCoreModule.cs
  58. 92
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/AutoMapperProfiles/Jobs/InjectionJobAutoMapperProfile.cs
  59. 134
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/AutoMapperProfiles/Requests/InjectionRequestAutoMapperProfile.cs
  60. 130
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/Jobs/InjectionJobEventHandler.cs
  61. 275
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/Requests/InjectionRequestEventHandler.cs
  62. 2
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/StoreEventAutoMapperProfile.cs

46
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/InjectionJobs/DTOs/InjectionJobDTO.cs

@ -0,0 +1,46 @@
using System.ComponentModel.DataAnnotations;
using Win_in.Sfs.Shared.Domain;
namespace Win_in.Sfs.Wms.Store.Application.Contracts;
/// <summary>
/// 注塑发料任务
/// </summary>
[Display(Name = "注塑发料任务")]
public class InjectionJobDTO : SfsJobDTOBase<InjectionJobDetailDTO>
{
/// <summary>
/// 叫料请求类型
/// </summary>
[Display(Name = "叫料请求类型")]
[StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
public string RequestType { get; set; }
/// <summary>
/// 生产线
/// </summary>
[Display(Name = "生产线")]
[StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
public string ProdLine { get; set; }
/// <summary>
/// 要货单号
/// </summary>
[Display(Name = "要货单号")]
[StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
public string InjectionRequestNumber { get; set; }
/// <summary>
/// 车间
/// </summary>
[Display(Name = "车间")]
[StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
public string Workshop { get; set; }
/// <summary>
/// 使用在途库
/// </summary>
[Display(Name = "使用在途库")]
public bool UseOnTheWayLocation { get; set; }
}

112
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/InjectionJobs/DTOs/InjectionJobDetailDTO.cs

@ -0,0 +1,112 @@
using System;
using System.ComponentModel.DataAnnotations;
using Win_in.Sfs.Shared.Domain;
using Win_in.Sfs.Shared.Domain.Shared;
namespace Win_in.Sfs.Wms.Store.Application.Contracts;
public class InjectionJobDetailDTO : SfsJobRecommendFromDetailDTOBase, IHasToLocation
{
/// <summary>
/// 请求库位
/// </summary>
[Display(Name = "请求库位")]
public string RequestLocationCode { get; set; }
/// <summary>
/// 到库位
/// </summary>
[Display(Name = "到库位")]
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; }
/// <summary>
/// 在途库库位
/// </summary>
[Display(Name = "在途库库位")]
public string OnTheWayLocationCode { get; set; }
/// <summary>
/// 生产线
/// </summary>
[Display(Name = "生产线")]
public string ProdLine { get; set; }
/// <summary>
/// 工作中心
/// </summary>
[Display(Name = "工作中心")]
public string WorkStation { get; set; }
/// <summary>
/// 过期时间
/// </summary>
[Display(Name = "过期时间")]
public DateTime ExpiredTime { get; set; }
/// <summary>
/// 工序
/// </summary>
[Display(Name = "工序")]
public string Operation { get; set; }
/// <summary>
/// 配送方式
/// </summary>
[Display(Name = "配送方式")]
public EnumDistributionType DistributionType { get; set; }
/// <summary>
/// 取整方式
/// </summary>
[Display(Name = "取整方式")]
public EnumTruncType TruncType { get; set; }
/// <summary>
/// 取整后数量
/// </summary>
[Display(Name = "取整后数量")]
public decimal RoundedQty { get; set; }
/// <summary>
/// 计划拆分规则
/// </summary>
[Display(Name = "计划拆分规则")]
public EnumPlannedSplitRule PlannedSplitRule { get; set; }
/// <summary>
/// 计划开始时间
/// </summary>
[Display(Name = "计划开始时间")]
public DateTime PlanBeginTime { get; set; }
/// <summary>
/// 每次配送数量
/// </summary>
[Display(Name = "每次配送数量")]
public decimal DeliveryQty { get; set; }
}

26
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/InjectionJobs/IInjectionJobAppService.cs

@ -0,0 +1,26 @@
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
namespace Win_in.Sfs.Wms.Store.Application.Contracts;
public interface IInjectionJobAppService
: ISfsJobAppServiceBase<InjectionJobDTO, SfsJobRequestInputBase, InjectionJobCheckInput, InjectionJobEditInput>
{
Task<List<InjectionJobDTO>> CheckJobExistByItemCodeAndLocationCode(string itemCode, string locationCode);
Task CancelByMaterialRequestAsync(string injectionNumber);
Task<PagedResultDto<InjectionJobDTO>> GetListByTypeAsync(SfsJobRequestInputBase requestInput, string requestType,
bool includeDetails = false, CancellationToken cancellationToken = default);
Task<List<InjectionJobDTO>> GetByRequestNumberAsync(string requestNumber);
/// <summary>
/// 保存拆箱时涉及的明细修改
/// </summary>
/// <returns></returns>
Task<InjectionJobDTO> SaveDetail_SplitPackingAsync(SplitPacking_UpdateJobDetailInput input);
}

27
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/InjectionJobs/InjectionJobPermissions.cs

@ -0,0 +1,27 @@
using Volo.Abp.Authorization.Permissions;
using Win_in.Sfs.Wms.Store.Domain;
namespace Win_in.Sfs.Wms.Store.Application.Contracts;
public static class InjectionJobPermissions
{
public const string Default = StorePermissions.GroupName + "." + nameof(InjectionJob);
public const string Create = Default + "." + StorePermissions.CreateStr;
public const string Update = Default + "." + StorePermissions.UpdateStr;
public const string Delete = Default + "." + StorePermissions.DeleteStr;
//自动发料任务
public const string AutoInjectionJob = StorePermissions.GroupName + "." + nameof(AutoInjectionJob);
public static void AddInjectionJobPermission(this PermissionGroupDefinition permissionGroup)
{
var InjectionJobPermission = permissionGroup.AddPermission(Default, StorePermissionDefinitionProvider.L(nameof(InjectionJob)));
InjectionJobPermission.AddChild(Create, StorePermissionDefinitionProvider.L(StorePermissions.CreateStr));
InjectionJobPermission.AddChild(Update, StorePermissionDefinitionProvider.L(StorePermissions.UpdateStr));
InjectionJobPermission.AddChild(Delete, StorePermissionDefinitionProvider.L(StorePermissions.DeleteStr));
permissionGroup.AddPermission(AutoInjectionJob, StorePermissionDefinitionProvider.L(nameof(AutoInjectionJob)));
}
}

6
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/InjectionJobs/Inputs/InjectionJobCheckInput.cs

@ -0,0 +1,6 @@
namespace Win_in.Sfs.Wms.Store.Application.Contracts;
public class InjectionJobCheckInput : SfsJobCheckInputBase
{
}

134
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/InjectionJobs/Inputs/InjectionJobDetailInput.cs

@ -0,0 +1,134 @@
using System;
using System.ComponentModel.DataAnnotations;
using Win_in.Sfs.Shared.Domain;
using Win_in.Sfs.Shared.Domain.Shared;
namespace Win_in.Sfs.Wms.Store.Application.Contracts;
public class InjectionJobDetailInput : SfsJobRecommendFromDetailInputBase, IHasToLocation
{
/// <summary>
/// 请求库位
/// </summary>
[Display(Name = "请求库位")]
[Required(ErrorMessage = "{0}是必填项")]
[StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
public string RequestLocationCode { get; set; }
/// <summary>
/// 到库位
/// </summary>
[Display(Name = "到库位")]
[Required(ErrorMessage = "{0}是必填项")]
[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库位")]
[Required(ErrorMessage = "{0}是必填项")]
[StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
public string ToLocationErpCode { get; set; }
/// <summary>
/// 到仓库
/// </summary>
[Display(Name = "到仓库")]
[Required(ErrorMessage = "{0}是必填项")]
[StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
public string ToWarehouseCode { get; set; }
/// <summary>
/// 在途库库位
/// </summary>
[Display(Name = "在途库库位")]
public string OnTheWayLocationCode { get; set; }
/// <summary>
/// 生产线
/// </summary>
[Display(Name = "生产线")]
[StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
public string ProdLine { get; set; }
/// <summary>
/// 工作中心
/// </summary>
[Display(Name = "工作中心")]
[StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
public string WorkStation { get; set; }
/// <summary>
/// 过期时间
/// </summary>
[Display(Name = "过期时间")]
[Required(ErrorMessage = "{0}是必填项")]
public DateTime ExpiredTime { get; set; }
/// <summary>
/// 工序
/// </summary>
[Display(Name = "工序")]
[StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
public string Operation { get; set; }
/// <summary>
/// 配送方式
/// </summary>
[Display(Name = "配送方式")]
public EnumDistributionType DistributionType { get; set; }
/// <summary>
/// 取整方式
/// </summary>
[Display(Name = "取整方式")]
public EnumTruncType TruncType { get; set; }
/// <summary>
/// 取整后数量
/// </summary>
[Display(Name = "取整后数量")]
public decimal RoundedQty { get; set; }
/// <summary>
/// 计划拆分规则
/// </summary>
[Display(Name = "计划拆分规则")]
public EnumPlannedSplitRule PlannedSplitRule { get; set; }
/// <summary>
/// 计划开始时间
/// </summary>
[Display(Name = "计划开始时间")]
public DateTime PlanBeginTime { get; set; }
/// <summary>
/// 每次配送数量
/// </summary>
[Display(Name = "每次配送数量")]
public decimal DeliveryQty { get; set; }
/// <summary>
/// 位置码
/// </summary>
public string PositionCode { get; set; }
/// <summary>
/// 推荐类型
/// </summary>
public EnumRecommendType RecommendType { get; set; }
}

82
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/InjectionJobs/Inputs/InjectionJobEditInput.cs

@ -0,0 +1,82 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using Win_in.Sfs.Shared.Domain;
using Win_in.Sfs.Shared.Domain.Shared;
namespace Win_in.Sfs.Wms.Store.Application.Contracts;
public class InjectionJobEditInput : SfsJobCreateUpdateInputBase, ISfsJobCreateInput<InjectionJobDetailInput>
{
#region Create
/// <summary>
/// 上游任务编号
/// </summary>
[Display(Name = "上游任务编号")]
[StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
public string UpStreamJobNumber { get; set; }
/// <summary>
/// 要货单号
/// </summary>
[Display(Name = "要货单号")]
[Required(ErrorMessage = "{0}是必填项")]
[StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
public string InjectionRequestNumber { get; set; }
/// <summary>
/// 叫料请求类型
/// </summary>
[Display(Name = "叫料请求类型")]
[StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
public string RequestType { get; set; }
/// <summary>
/// 任务类型
/// </summary>
[Display(Name = "任务类型")]
[Required(ErrorMessage = "{0}是必填项")]
public EnumJobType JobType { get; set; }
/// <summary>
/// 是否自动完成
/// </summary>
[Display(Name = "是否自动完成")]
[Required(ErrorMessage = "{0}是必填项")]
public bool IsAutoComplete { get; set; }
/// <summary>
/// 过期时间
/// </summary>
[Display(Name = "过期时间")]
[Required(ErrorMessage = "{0}是必填项")]
public DateTime ExpiredTime { get; set; }
/// <summary>
/// 任务明细
/// </summary>
[Display(Name = "任务明细")]
[Required(ErrorMessage = "{0}是必填项")]
public List<InjectionJobDetailInput> Details { get; set; } = new();
/// <summary>
/// 车间
/// </summary>
[Display(Name = "车间")]
[StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
public string Workshop { get; set; }
/// <summary>
/// 生产线
/// </summary>
[Display(Name = "生产线")]
[StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
public string ProdLine { get; set; }
/// <summary>
/// 使用在途库
/// </summary>
[Display(Name = "使用在途库")]
public bool UseOnTheWayLocation { get; set; }
#endregion
}

54
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/InjectionNotes/DTOs/InjectionNoteDTO.cs

@ -0,0 +1,54 @@
using System;
using System.ComponentModel.DataAnnotations;
using Win_in.Sfs.Shared.Domain;
namespace Win_in.Sfs.Wms.Store.Application.Contracts;
public class InjectionNoteDTO : SfsStoreDTOBase<InjectionNoteDetailDTO>, IHasJobNumber, IHasRequestNumber
{
/// <summary>
/// 任务ID
/// </summary>
[Display(Name = "任务ID")]
public string JobNumber { get; set; }
/// <summary>
/// 车间
/// </summary>
[Display(Name = "车间")]
[StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
public string Workshop { get; set; }
/// <summary>
/// 请求代码
/// </summary>
[Display(Name = "请求代码")]
public string RequestNumber { get; set; }
/// <summary>
/// 叫料请求类型
/// </summary>
[Display(Name = "叫料请求类型")]
[StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
public string RequestType { get; set; }
/// <summary>
/// 使用在途库
/// </summary>
[Display(Name = "使用在途库")]
public bool UseOnTheWayLocation { get; set; }
/// <summary>
/// 已确认
/// </summary>
[Display(Name = "已确认")]
public bool Confirmed { get; set; }
/// <summary>
/// 确认时间
/// </summary>
[Display(Name = "确认时间")]
public DateTime? ConfirmTime { get; set; }
}

42
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/InjectionNotes/DTOs/InjectionNoteDetailDTO.cs

@ -0,0 +1,42 @@
using System;
using System.ComponentModel.DataAnnotations;
using Win_in.Sfs.Shared.Domain;
namespace Win_in.Sfs.Wms.Store.Application.Contracts;
public class InjectionNoteDetailDTO : SfsStoreRecommendFromDetailWithFromToDTOBase
{
/// <summary>
/// 发料时间
/// </summary>
[Display(Name = "发料时间")]
public DateTime IssueTime { get; set; }
/// <summary>
/// 过期时间
/// </summary>
[Display(Name = "过期时间")]
public DateTime ExpiredTime { get; set; }
/// <summary>
/// 生产线
/// </summary>
[Display(Name = "生产线")]
[StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
public string ProdLine { get; set; }
/// <summary>
/// 工作中心
/// </summary>
[Display(Name = "工作中心")]
[StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
public string WorkStation { get; set; }
/// <summary>
/// 在途库库位
/// </summary>
[Display(Name = "在途库库位")]
public string OnTheWayLocationCode { get; set; }
}

21
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/InjectionNotes/IInjectionNoteAppService.cs

@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
namespace Win_in.Sfs.Wms.Store.Application.Contracts;
public interface IInjectionNoteAppService : ISfsStoreMasterReadOnlyAppServiceBase<InjectionNoteDTO, SfsStoreRequestInputBase, InjectionNoteDetailDTO, SfsStoreRequestInputBase>
{
Task<InjectionNoteDTO> CreateAsync(InjectionNoteEditInput input);
Task<InjectionNoteDTO> ConfirmAsync(Guid id);
Task<InjectionNoteDTO> ConfirmAsync(string number);
Task<PagedResultDto<InjectionNoteDTO>> GetListByTypeAsync(SfsStoreRequestInputBase requestInput,
string requestType, bool includeDetails = false, CancellationToken cancellationToken = default);
Task<List<InjectionNoteDTO>> GetListUnConfirmedByTypeAsync(string requestType);
}

30
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/InjectionNotes/InjectionNotePermissions.cs

@ -0,0 +1,30 @@
using Volo.Abp.Authorization.Permissions;
using Win_in.Sfs.Wms.Store.Domain;
namespace Win_in.Sfs.Wms.Store.Application.Contracts;
public static class InjectionNotePermissions
{
public const string Default = StorePermissions.GroupName + "." + nameof(InjectionNote);
public const string Create = Default + "." + StorePermissions.CreateStr;
public const string Update = Default + "." + StorePermissions.UpdateStr;
public const string Delete = Default + "." + StorePermissions.DeleteStr;
//自动发料记录
public const string AutoInjectionNote = StorePermissions.GroupName + "." + nameof(AutoInjectionNote);
//直接发料
public const string DirectInjectionNote = StorePermissions.GroupName + "." + nameof(DirectInjectionNote);
public static void AddInjectionNotePermission(this PermissionGroupDefinition permissionGroup)
{
var injectionNotePermission = permissionGroup.AddPermission(Default, StorePermissionDefinitionProvider.L(nameof(InjectionNote)));
injectionNotePermission.AddChild(Create, StorePermissionDefinitionProvider.L(StorePermissions.CreateStr));
injectionNotePermission.AddChild(Update, StorePermissionDefinitionProvider.L(StorePermissions.UpdateStr));
injectionNotePermission.AddChild(Delete, StorePermissionDefinitionProvider.L(StorePermissions.DeleteStr));
permissionGroup.AddPermission(AutoInjectionNote, StorePermissionDefinitionProvider.L(nameof(AutoInjectionNote)));
permissionGroup.AddPermission(DirectInjectionNote, StorePermissionDefinitionProvider.L(nameof(DirectInjectionNote)));
}
}

53
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/InjectionNotes/Inputs/InjectionNoteDetailInput.cs

@ -0,0 +1,53 @@
using System;
using System.ComponentModel.DataAnnotations;
using Win_in.Sfs.Shared.Domain;
using Win_in.Sfs.Shared.Domain.Shared;
namespace Win_in.Sfs.Wms.Store.Application.Contracts;
public class InjectionNoteDetailInput : SfsStoreRecommendFromDetailWithFromToInputBase
{
/// <summary>
/// 发料时间
/// </summary>
[Display(Name = "发料时间")]
public DateTime IssueTime { get; set; }
/// <summary>
/// 过期时间
/// </summary>
[Display(Name = "过期时间")]
public DateTime ExpiredTime { get; set; }
/// <summary>
/// 生产线
/// </summary>
[Display(Name = "生产线")]
[StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
public string ProdLine { get; set; }
/// <summary>
/// 工作中心
/// </summary>
[Display(Name = "工作中心")]
[StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
public string WorkStation { get; set; }
/// <summary>
/// 在途库库位
/// </summary>
[Display(Name = "在途库库位")]
public string OnTheWayLocationCode { get; set; }
/// <summary>
/// 位置码
/// </summary>
public string PositionCode { get; set; }
/// <summary>
/// 推荐类型
/// </summary>
public EnumRecommendType RecommendType { get; set; }
}

63
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/InjectionNotes/Inputs/InjectionNoteEditInput.cs

@ -0,0 +1,63 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using Win_in.Sfs.Shared.Domain;
namespace Win_in.Sfs.Wms.Store.Application.Contracts;
public class InjectionNoteEditInput : SfsStoreCreateOrUpdateInputBase
{
#region Base
/// <summary>
/// 已确认
/// </summary>
[Display(Name = "已确认")]
public bool Confirmed { get; set; }
#endregion
#region Create
/// <summary>
/// 发料记录号
/// </summary>
[Display(Name = "发料记录号")]
public string Number { get; set; }
/// <summary>
/// 任务ID
/// </summary>
[Display(Name = "任务ID")]
[Required(ErrorMessage = "{0}是必填项")]
public string JobNumber { get; set; }
/// <summary>
/// 车间
/// </summary>
[Display(Name = "车间")]
[StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
public string Workshop { get; set; }
/// <summary>
/// 明细列表
/// </summary>
[Display(Name = "明细列表")]
public List<InjectionNoteDetailInput> Details { get; set; }
/// <summary>
/// 请求号码
/// </summary>
[Display(Name = "请求号码")]
public string RequestNumber { get; set; }
/// <summary>
/// 叫料请求类型
/// </summary>
[Display(Name = "叫料请求类型")]
[StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
public string RequestType { get; set; }
/// <summary>
/// 使用在途库
/// </summary>
[Display(Name = "使用在途库")]
public bool UseOnTheWayLocation { get; set; }
#endregion
}

33
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/InjectionNotes/Inputs/InjectionNoteImportInput.cs

@ -0,0 +1,33 @@
using System.ComponentModel.DataAnnotations;
namespace Win_in.Sfs.Wms.Store.Application.Contracts;
public class InjectionNoteImportInput : SfsStoreImportInputBase, IHasJobNumber, IHasRequestNumber
{
/// <summary>
/// 任务ID
/// </summary>
[Display(Name = "任务ID")]
public string JobNumber { get; set; }
/// <summary>
/// 车间
/// </summary>
[Display(Name = "车间")]
public string Workshop { get; set; }
public string RequestNumber { get; set; }
/// <summary>
/// 叫料请求类型
/// </summary>
[Display(Name = "叫料请求类型")]
public string RequestType { get; set; }
/// <summary>
/// 使用在途库
/// </summary>
[Display(Name = "使用在途库")]
[Required(ErrorMessage = "{0}是必填项")]
public bool UseOnTheWayLocation { get; set; }
}

3
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Permissions/StorePermissionDefinitionProvider.cs

@ -26,8 +26,10 @@ public class StorePermissionDefinitionProvider : PermissionDefinitionProvider
storeGroup.AddPurchaseReturnNotePermission();
storeGroup.AddPutawayNotePermission();
storeGroup.AddMaterialRequestPermission();
storeGroup.AddInjectionRequestPermission();
storeGroup.AddContainerRequestPermission();
storeGroup.AddIssueNotePermission();
storeGroup.AddInjectionNotePermission();
storeGroup.AddContainerNotePermission();
storeGroup.AddUnplannedReceiptNotePermission();
storeGroup.AddUnplannedIssueNotePermission();
@ -90,6 +92,7 @@ public class StorePermissionDefinitionProvider : PermissionDefinitionProvider
storeGroup.AddInspectJobPermission();
storeGroup.AddPutawayJobPermission();
storeGroup.AddIssueJobPermission();
storeGroup.AddInjectionJobPermission();
storeGroup.AddContainerJobPermission();
storeGroup.AddDeliverJobPermission();
storeGroup.AddPurchaseReturnJobPermission();

37
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/InjectionRequests/DTOs/InjectionRequestDTO.cs

@ -0,0 +1,37 @@
using System.ComponentModel.DataAnnotations;
namespace Win_in.Sfs.Wms.Store.Application.Contracts;
public class InjectionRequestDTO : SfsStoreRequestDTOBase<InjectionRequestDetailDTO>, IHasNumber
{
/// <summary>
/// 叫料类型
/// </summary>
[Display(Name = "叫料类型")]
public string Type { get; set; }
/// <summary>
/// 备料计划单号
/// </summary>
[Display(Name = "备料计划单号")]
public string PreparationPlanNumber { get; set; }
/// <summary>
/// 生产线
/// </summary>
[Display(Name = "生产线")]
public string ProdLine { get; set; }
/// <summary>
/// 车间
/// </summary>
[Display(Name = "车间")]
public string Workshop { get; set; }
/// <summary>
/// 使用在途库
/// </summary>
[Display(Name = "使用在途库")]
public bool UseOnTheWayLocation { get; set; }
}

94
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/InjectionRequests/DTOs/InjectionRequestDetailDTO.cs

@ -0,0 +1,94 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Win_in.Sfs.Shared.Domain;
using Win_in.Sfs.Shared.Domain.Shared;
namespace Win_in.Sfs.Wms.Store.Application.Contracts;
public class InjectionRequestDetailDTO : SfsStoreDetailWithQtyDTOBase
{
/// <summary>
/// 目标库位
/// </summary>
[Display(Name = "目标库位")]
public string ToLocationCode { get; set; }
/// <summary>
/// 来源库区
/// </summary>
[Display(Name = "来源库区")]
[StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
public string FromLocationArea { get; set; }
// /// <summary>
// /// 在途库库位
// /// </summary>
// public string OnTheWayLocationCode { get; set; }
/// <summary>
/// 生产线
/// </summary>
[Display(Name = "生产线")]
public string ProdLine { get; set; }
/// <summary>
/// 工作中心
/// </summary>
[Display(Name = "工作中心")]
public string WorkStation { get; set; }
/// <summary>
/// 过期时间
/// </summary>
[Display(Name = "过期时间")]
public DateTime ExpiredTime { get; set; }
/// <summary>
/// 目标ERP储位
/// </summary>
[Display(Name = "目标ERP储位")]
public string ToLocationErpCode { 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;
}

35
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/InjectionRequests/IInjectionRequestAppService.cs

@ -0,0 +1,35 @@
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
namespace Win_in.Sfs.Wms.Store.Application.Contracts;
public interface IInjectionRequestAppService
: ISfsStoreRequestMasterAppServiceBase<InjectionRequestDTO, SfsStoreRequestInputBase, InjectionRequestEditInput, InjectionRequestDetailDTO, SfsStoreRequestInputBase>
{
Task<InjectionRequestDTO> CreateAndHandleAsync(InjectionRequestEditInput input);
/// <summary>
/// 根据备料计划生成 叫料请求
/// </summary>
/// <returns></returns>
Task<InjectionRequestDTO> CreateAndHandleByPreparationPlan(string productionPlanNumber);
Task<InjectionRequestDTO> CreateAndHandleByAPIAsync(InjectionRequestEditInput input);
/// <summary>
/// 根据类型获取叫料请求
/// </summary>
/// <param name="requestInput"></param>
/// <param name="type">叫料请求类型</param>
/// <param name="includeDetails"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<PagedResultDto<InjectionRequestDTO>> GetListByTypeAsync(SfsStoreRequestInputBase requestInput,
string type, bool includeDetails = false, CancellationToken cancellationToken = default);
Task<List<InjectionRequestDTO>> GetListByTypeAsync(string type);
}

27
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/InjectionRequests/InjectionRequestPermissions.cs

@ -0,0 +1,27 @@
using Volo.Abp.Authorization.Permissions;
using Win_in.Sfs.Wms.Store.Domain;
namespace Win_in.Sfs.Wms.Store.Application.Contracts;
public static class InjectionRequestPermissions
{
public const string Default = StorePermissions.GroupName + "." + nameof(InjectionRequest);
public const string Create = Default + "." + StorePermissions.CreateStr;
public const string Update = Default + "." + StorePermissions.UpdateStr;
public const string Delete = Default + "." + StorePermissions.DeleteStr;
//自动叫料申请
public const string AutoInjectionRequest = StorePermissions.GroupName + "." + nameof(AutoInjectionRequest);
public static void AddInjectionRequestPermission(this PermissionGroupDefinition permissionGroup)
{
var InjectionRequestPermission = permissionGroup.AddPermission(Default, StorePermissionDefinitionProvider.L(nameof(InjectionRequest)));
InjectionRequestPermission.AddChild(Create, StorePermissionDefinitionProvider.L(StorePermissions.CreateStr));
InjectionRequestPermission.AddChild(Update, StorePermissionDefinitionProvider.L(StorePermissions.UpdateStr));
InjectionRequestPermission.AddChild(Delete, StorePermissionDefinitionProvider.L(StorePermissions.DeleteStr));
permissionGroup.AddPermission(AutoInjectionRequest, StorePermissionDefinitionProvider.L(nameof(AutoInjectionRequest)));
}
}

85
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/InjectionRequests/Inputs/InjectionRequestDetailInput.cs

@ -0,0 +1,85 @@
using System;
using System.ComponentModel.DataAnnotations;
using Win_in.Sfs.Shared.Domain;
using Win_in.Sfs.Shared.Domain.Shared;
namespace Win_in.Sfs.Wms.Store.Application.Contracts;
public class InjectionRequestDetailInput : SfsStoreDetailWithQtyInputBase
{
/// <summary>
/// 目标库位
/// </summary>
[Display(Name = "目标库位")]
[StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
public string ToLocationCode { get; set; }
/// <summary>
/// 来源库区
/// </summary>
[Display(Name = "来源库区")]
[StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
public string FromLocationArea { get; set; }
/// <summary>
/// 生产线
/// </summary>
[Display(Name = "生产线")]
[StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
public string ProdLine { get; set; }
/// <summary>
/// 工作中心
/// </summary>
[Display(Name = "工作中心")]
[StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
public string WorkStation { get; set; }
/// <summary>
/// 过期时间
/// </summary>
[Display(Name = "过期时间")]
public DateTime ExpiredTime { get; set; }
/// <summary>
/// 状态
/// </summary>
[Display(Name = "状态")]
public EnumRequestStatus RequestStatus { get; set; } = EnumRequestStatus.New;
/// <summary>
/// ERP储位
/// </summary>
[Display(Name = "ERP储位")]
public string ToLocationErpCode { 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>
public string PositionCode { get; set; }
/// <summary>
/// 推荐类型
/// </summary>
public EnumRecommendType RecommendType { get; set; }
}

58
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/InjectionRequests/Inputs/InjectionRequestEditInput.cs

@ -0,0 +1,58 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using Win_in.Sfs.Shared.Domain;
namespace Win_in.Sfs.Wms.Store.Application.Contracts;
public class InjectionRequestEditInput : SfsStoreRequestCreateOrUpdateInputBase
{
#region Base
/// <summary>
/// 车间
/// </summary>
[Display(Name = "车间")]
[StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
public string Workshop { get; set; }
/// <summary>
/// 生产线
/// </summary>
[Display(Name = "生产线")]
[StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
public string ProdLine { get; set; }
/// <summary>
/// 使用在途库
/// </summary>
[Display(Name = "使用在途库")]
public bool UseOnTheWayLocation { get; set; }
#endregion
#region Create
/// <summary>
/// 要货单号
/// </summary>
[Display(Name = "要货单号")]
[StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
public string Number { get; set; }
/// <summary>
/// 叫料类型
/// </summary>
[Display(Name = "叫料类型")]
public string Type { get; set; }
/// <summary>
/// 备料计划单号
/// </summary>
[Display(Name = "备料计划单号")]
[StringLength(SfsEfCorePropertyConst.CodeLength, ErrorMessage = "{0}最多输入{1}个字符")]
public string PreparationPlanNumber { get; set; }
/// <summary>
/// 明细列表
/// </summary>
[Display(Name = "明细列表")]
public List<InjectionRequestDetailInput> Details { get; set; } = new List<InjectionRequestDetailInput>();
#endregion
}

53
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/InjectionRequests/Inputs/InjectionRequestImportInput.cs

@ -0,0 +1,53 @@
using System.ComponentModel.DataAnnotations;
using Win_in.Sfs.Shared.Application.Contracts;
using Win_in.Sfs.Shared.Domain.Shared;
namespace Win_in.Sfs.Wms.Store.Application.Contracts;
[Display(Name = "叫料申请")]
public class InjectionRequestImportInput : SfsStoreImportInputBase
{
/// <summary>
/// 叫料类型
/// </summary>
[Display(Name = "叫料类型")]
[Required(ErrorMessage = "{0}是必填项")]
[ImporterHeader(Name = "叫料类型")]
[ExporterHeader(DisplayName = "叫料类型")]
[ValueMapping("人工拉动", EnumMaterialRequestType.Issue_Manual)]
public string Type { get; set; }
/// <summary>
/// 物品代码
/// </summary>
[Display(Name = "物品代码")]
[Required]
public string ItemCode { get; set; }
/// <summary>
/// 目标库位
/// </summary>
[Display(Name = "目标库位")]
[Required]
public string ToLocationCode { get; set; }
/// <summary>
/// 来源库区
/// </summary>
[Display(Name = "调出库区")]
[Required]
public string FromLocationArea { get; set; }
/// <summary>
/// 数量
/// </summary>
[Display(Name = "数量")]
[Required(ErrorMessage = "{0}是必填项")]
public decimal Qty { get; set; }
/// <summary>
/// 备注
/// </summary>
[Display(Name = "备注")]
public string Remark { get; set; }
}

144
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Jobs/InjectionJobs/InjectionJobAppService.cs

@ -0,0 +1,144 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.ObjectMapping;
using Win_in.Sfs.Basedata.Domain.Shared;
using Win_in.Sfs.Shared.Domain;
using Win_in.Sfs.Shared.Domain.Shared;
using Win_in.Sfs.Wms.Store.Application.Contracts;
using Win_in.Sfs.Wms.Store.Domain;
using Win_in.Sfs.Wms.Store.Domain.Shared;
namespace Win_in.Sfs.Wms.Store.Application;
[Authorize]
[Route($"{StoreConsts.RootPath}injection-job")]
public class InjectionJobAppService
: SfsJobAppServiceBase<InjectionJob, InjectionJobDetail, InjectionJobDTO, SfsJobRequestInputBase, InjectionJobCheckInput, InjectionJobEditInput>,
IInjectionJobAppService
{
private readonly IInjectionJobManager _injectionJobManager;
public InjectionJobAppService(
IInjectionJobRepository repository, IInjectionJobManager injectionJobManager
) : base(repository, injectionJobManager)
{
_injectionJobManager = injectionJobManager;
}
/// <summary>
/// 根据物品和库位 检查是否存在发料任务
/// </summary>
/// <param name="itemCode"></param>
/// <param name="locationCode"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
[Authorize]
[HttpGet("check-job-exist")]
public virtual async Task<List<InjectionJobDTO>> CheckJobExistByItemCodeAndLocationCode(string itemCode,
string locationCode)
{
var entities = await _repository.GetListAsync(c =>
c.Details.Any(p =>
(p.ItemCode == itemCode && p.RecommendFromLocationCode == locationCode) ||
(p.ItemCode == itemCode && p.ToLocationCode == locationCode))
&& (c.JobStatus == EnumJobStatus.Open || c.JobStatus == EnumJobStatus.Doing), true).ConfigureAwait(false);
var dtos = ObjectMapper.Map<List<InjectionJob>, List<InjectionJobDTO>>(entities);
return dtos;
}
[HttpPost("cancel-by-request/{injectionNumber}")]
public virtual async Task CancelByMaterialRequestAsync(string injectionNumber)
{
var entities = await _repository.GetListAsync(p => p.InjectionRequestNumber == injectionNumber).ConfigureAwait(false);
foreach (var entity in entities)
{
await _injectionJobManager.CancelAsync(entity).ConfigureAwait(false);
}
}
[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 _injectionJobManager.CancelAsync(injectionJob).ConfigureAwait(false);
}
/// <summary>
/// 根据叫料请求类型获取发料任务
/// </summary>
/// <param name="requestInput"></param>
/// <param name="requestType">
/// 叫料请求类型:
/// 人工拉动:Issue_Manual;
/// 线边拉动:Issue_WIP;
/// </param>
/// <param name="includeDetails"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpPost("by-type/{requestType}")]
public virtual async Task<PagedResultDto<InjectionJobDTO>> GetListByTypeAsync(SfsJobRequestInputBase requestInput,
string requestType, bool includeDetails = false, CancellationToken cancellationToken = default)
{
Expression<Func<InjectionJob, bool>> expression = p => p.RequestType == requestType;
if (requestInput.Condition.Filters?.Count > 0)
{
expression = expression.And(requestInput.Condition.Filters.ToLambda<InjectionJob>());
}
return await GetPagedListAsync(expression, requestInput.SkipCount, requestInput.MaxResultCount,
requestInput.Sorting, includeDetails, cancellationToken).ConfigureAwait(false);
}
[HttpPost("by-request-number/{requestNumber}")]
public virtual async Task<List<InjectionJobDTO>> GetByRequestNumberAsync(string requestNumber)
{
var entitys = await _repository.GetListAsync(p => p.InjectionRequestNumber == requestNumber).ConfigureAwait(false);
return ObjectMapper.Map<List<InjectionJob>, List<InjectionJobDTO>>(entitys);
}
/// <summary>
/// 保存拆箱时涉及的明细修改
/// </summary>
/// <returns></returns>
[HttpPost("save-detail-split-packing")]
public virtual async Task<InjectionJobDTO> SaveDetail_SplitPackingAsync(SplitPacking_UpdateJobDetailInput input)
{
var job = await _repository.FindAsync(p => p.Number == input.Number).ConfigureAwait(false);
InjectionJobDetail detail = job.Details.FirstOrDefault(p => p.RecommendPackingCode == input.FromPackingCode ); /*&& p.HandledQty == input.FromQty*/
if (detail == null)
{
//throw new UserFriendlyException($"根据HandledPackingCode={input.FromPackingCode}取InjectionJobDetail表为空!");
throw new UserFriendlyException($"根据RecommendPackingCode={input.FromPackingCode}取InjectionJobDetail表为空!");
}
//插入目标箱
var newDetail = CommonHelper.CloneObj(detail);
newDetail.SetId(GuidGenerator.Create());
newDetail.RecommendPackingCode = input.ToPackingCode;
newDetail.RecommendQty = input.ToQty;
newDetail.HandledPackingCode = detail.HandledPackingCode.HasValue() ? input.ToPackingCode : null; //源实际实际箱码有值,则新记录实际箱码有值
newDetail.HandledQty = detail.HandledQty > 0 ? input.ToQty : 0;
//newDetail.CreationTime = CommonHelper.CurTime;
job.Details.Add(newDetail);
//修改源箱
detail.RecommendQty = input.FromQty - input.ToQty;
detail.HandledQty = detail.HandledQty > 0 ? input.FromQty - input.ToQty : 0;
var entity = await _repository.UpdateAsync(job).ConfigureAwait(false);
var ret = ObjectMapper.Map<InjectionJob, InjectionJobDTO>(entity);
return ret;
}
}

30
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Jobs/InjectionJobs/InjectionJobAutoMapperProfile.cs

@ -0,0 +1,30 @@
using AutoMapper;
using Volo.Abp.AutoMapper;
using Win_in.Sfs.Wms.Store.Application.Contracts;
using Win_in.Sfs.Wms.Store.Domain;
namespace Win_in.Sfs.Wms.Store.Application;
public partial class StoreApplicationAutoMapperProfile : Profile
{
private void InjectionJobAutoMapperProfile()
{
CreateMap<InjectionJob, InjectionJobDTO>();
CreateMap<InjectionJobDTO, InjectionJob>();
CreateMap<InjectionJobDetail, InjectionJobDetailDTO>()
;
CreateMap<InjectionJobDetailDTO, InjectionJobDetail>()
;
CreateMap<InjectionJobDetailInput, InjectionJobDetail>()
.IgnoreAuditedObjectProperties()
.Ignore(x => x.MasterID)
.Ignore(x => x.TenantId)
.Ignore(x => x.Number)
.Ignore(x => x.Id);
}
}

108
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Notes/InjectionNotes/InjectionNoteAppService.cs

@ -0,0 +1,108 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Domain.Entities;
using Win_in.Sfs.Shared.Domain;
using Win_in.Sfs.Shared.Event;
using Win_in.Sfs.Wms.Store.Application.Contracts;
using Win_in.Sfs.Wms.Store.Domain;
using Win_in.Sfs.Wms.Store.Domain.Shared;
namespace Win_in.Sfs.Wms.Store.Application;
[Authorize]
[Route($"{StoreConsts.RootPath}injection-note")]
public class InjectionNoteAppService :
SfsStoreWithDetailsAppServiceBase<InjectionNote, InjectionNoteDTO, SfsStoreRequestInputBase, InjectionNoteEditInput, InjectionNoteDetail,
InjectionNoteDetailDTO, SfsStoreRequestInputBase, InjectionNoteImportInput>,
IInjectionNoteAppService
{
private readonly IInjectionNoteManager _injectionNoteManager;
public InjectionNoteAppService(
IInjectionNoteRepository repository,
IInjectionNoteManager injectionNoteManager
) : base(repository)
{
_injectionNoteManager = injectionNoteManager;
}
[HttpPost("")]
//[Authorize(InjectionNotePermissions.Create)]
public override async Task<InjectionNoteDTO> CreateAsync(InjectionNoteEditInput input)
{
var entity = ObjectMapper.Map<InjectionNoteEditInput, InjectionNote>(input);
await _injectionNoteManager.CreateAsync(entity).ConfigureAwait(false);
var dto = ObjectMapper.Map<InjectionNote, InjectionNoteDTO>(entity);
return dto;
}
/// <summary>
/// 确认对应的记录单
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
[HttpPost("confirm/{id}")]
public virtual async Task<InjectionNoteDTO> ConfirmAsync(Guid id)
{
var injectionNote= await _repository.GetAsync(id).ConfigureAwait(false);
injectionNote.Confirmed = true;
injectionNote=await _repository.UpdateAsync(injectionNote).ConfigureAwait(false);
await LocalEventBus.PublishAsync(new SfsConfirmedEntityEventData<InjectionNote>(injectionNote), false).ConfigureAwait(false);
return ObjectMapper.Map<InjectionNote, InjectionNoteDTO>(injectionNote);
}
[HttpPost("confirm-by-number/{number}")]
public virtual async Task<InjectionNoteDTO> ConfirmAsync(string number)
{
var entity = await _repository.FindAsync(p => p.Number == number).ConfigureAwait(false);
Check.NotNull(entity, nameof(InjectionNote));
var result = await _injectionNoteManager.ConfirmAsync(entity.Id).ConfigureAwait(false);
var dto = ObjectMapper.Map<InjectionNote, InjectionNoteDTO>(result);
return dto;
}
/// <summary>
/// 根据叫料请求类型获取发料记录
/// </summary>
/// <param name="requestInput"></param>
/// <param name="requestType">
/// 叫料请求类型:
/// 人工拉动:Issue_Manual;
/// 线边拉动:Issue_WIP;
/// </param>
/// <param name="includeDetails"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpPost("by-type/{requestType}")]
public virtual async Task<PagedResultDto<InjectionNoteDTO>> GetListByTypeAsync(SfsStoreRequestInputBase requestInput,
string requestType, bool includeDetails = false, CancellationToken cancellationToken = default)
{
Expression<Func<InjectionNote, bool>> expression = p => p.RequestType == requestType;
if (requestInput.Condition.Filters?.Count > 0)
{
expression = expression.And(requestInput.Condition.Filters.ToLambda<InjectionNote>());
}
return await GetPagedListAsync(expression, requestInput.SkipCount, requestInput.MaxResultCount,
requestInput.Sorting, includeDetails, cancellationToken).ConfigureAwait(false);
}
[HttpGet("list/un-confirmed/{requestType}")]
public virtual async Task<List<InjectionNoteDTO>> GetListUnConfirmedByTypeAsync(string requestType)
{
var entities = await _repository.GetListAsync(c => !c.Confirmed && c.RequestType == requestType)
.ConfigureAwait(false);
var dtos = ObjectMapper.Map<List<InjectionNote>, List<InjectionNoteDTO>>(entities);
return dtos;
}
}

31
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Notes/InjectionNotes/InjectionNoteAutoMapperProfile.cs

@ -0,0 +1,31 @@
using AutoMapper;
using Volo.Abp.AutoMapper;
using Win_in.Sfs.Wms.Store.Application.Contracts;
using Win_in.Sfs.Wms.Store.Domain;
namespace Win_in.Sfs.Wms.Store.Application;
public partial class StoreApplicationAutoMapperProfile : Profile
{
private void InjectionNoteAutoMapperProfile()
{
CreateMap<InjectionNote, InjectionNoteDTO>()
.ReverseMap();
CreateMap<InjectionNoteDetail, InjectionNoteDetailDTO>();
CreateMap<InjectionNoteDetailInput, InjectionNoteDetail>()
.IgnoreAuditedObjectProperties()
.Ignore(x => x.MasterID)
.Ignore(x => x.TenantId)
.Ignore(x => x.Number)
.Ignore(x => x.Id);
CreateMap<InjectionNoteEditInput, InjectionNote>()
.IgnoreAuditedObjectProperties()
.Ignore(x => x.TenantId)
.Ignore(x => x.Number)
.Ignore(x => x.Id);
;
}
}

2
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Notes/ProductRecycleNotes/ProductRecycleNoteAutoMapperProfile.cs

@ -15,6 +15,8 @@ public partial class StoreApplicationAutoMapperProfile : Profile
CreateMap<ProductRecycleNoteEditInput, ProductRecycleNote>();
CreateMap<ProductRecycleNoteImportInput, ProductRecycleNote>();
CreateMap<ProductRecycleNoteDetailInput, ProductRecycleNoteDetail>()
.IgnoreAuditedObjectProperties()
.Ignore(x => x.MasterID)

503
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Requests/InjectionRequests/InjectionRequestAppService.cs

@ -0,0 +1,503 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
using DocumentFormat.OpenXml.Office.PowerPoint.Y2021.M06.Main;
using IdentityModel;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Domain.Entities;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.ObjectMapping;
using Win_in.Sfs.Basedata.Application.Contracts;
using Win_in.Sfs.Shared.Domain;
using Win_in.Sfs.Shared.Domain.Shared;
using Win_in.Sfs.Shared.Event;
using Win_in.Sfs.Wms.Store.Application.Contracts;
using Win_in.Sfs.Wms.Store.Domain;
using Win_in.Sfs.Wms.Store.Domain.Shared;
namespace Win_in.Sfs.Wms.Store.Application;
[Authorize]
[Route($"{StoreConsts.RootPath}injection-request")]
public class InjectionRequestAppService : SfsStoreRequestAppServiceBase<InjectionRequest, InjectionRequestDTO,
SfsStoreRequestInputBase, InjectionRequestEditInput, InjectionRequestDetail, InjectionRequestDetailDTO,
SfsStoreRequestInputBase, InjectionRequestImportInput>,
IInjectionRequestAppService
{
private readonly IInjectionRequestManager _injectionRequestManager;
private readonly IPreparationPlanManager _preparationPlanManager;
private readonly IItemStoreRelationAppService _itemStoreRelationApp;
private readonly IAreaAppService _areaApp;
private readonly ILocationAppService _locationAppService;
private readonly IItemBasicAppService _itemBasicAppService;
private readonly IProductionLineAppService _productionLineAppService;
private readonly IInjectionJobAppService _issueJobAppService;
public InjectionRequestAppService(
IInjectionRequestRepository repository,
IInjectionRequestManager injectionRequestManager,
IPreparationPlanManager preparationPlanManager,
IItemStoreRelationAppService itemStoreRelationApp,
IAreaAppService areaApp,
ILocationAppService locationAppService,
IItemBasicAppService itemBasicAppService,
IProductionLineAppService productionLineAppService,
IInjectionJobAppService issueJobAppService)
: base(repository, injectionRequestManager)
{
_injectionRequestManager = injectionRequestManager;
_preparationPlanManager = preparationPlanManager;
_itemStoreRelationApp = itemStoreRelationApp;
_areaApp = areaApp;
_locationAppService = locationAppService;
_itemBasicAppService = itemBasicAppService;
_productionLineAppService = productionLineAppService;
_issueJobAppService = issueJobAppService;
}
#region 东阳使用
/// <summary>
/// 用来重写 导入数据时可以加工数据
/// </summary>
/// <param name="dictionary"></param>
/// <returns></returns>
protected override async Task<Dictionary<InjectionRequest, EntityState>> ImportProcessingEntityAsync(
Dictionary<InjectionRequest, EntityState> dictionary)
{
var addList = dictionary.Where(p => p.Value == EntityState.Added).Select(p => p.Key);
foreach (var injectionRequest in addList)
{
injectionRequest.Worker = CurrentUser.GetUserName();
injectionRequest.CreatorId = CurrentUser.Id;
if (injectionRequest.Type == EnumTransSubType.Issue_Manual.GetDisplayName())
{
injectionRequest.Type = EnumTransSubType.Issue_Manual.ToString();
}
foreach (var detail in injectionRequest.Details)
{
var locationDto= await _locationAppService.GetByCodeAsync(detail.ToLocationCode).ConfigureAwait(false);
CheckLocation(locationDto,detail.ToLocationCode);
var itemBasicDto=await _itemBasicAppService.GetByCodeAsync(detail.ItemCode).ConfigureAwait(false);
CheckItemBasic(itemBasicDto,detail.ItemCode);
detail.ToLocationArea = locationDto.AreaCode;
detail.ToLocationErpCode = locationDto.ErpLocationCode;
detail.ToLocationGroup = locationDto.LocationGroupCode;
detail.ToWarehouseCode = locationDto.WarehouseCode;
detail.ItemDesc1 = itemBasicDto.Desc1;
detail.ItemDesc2= itemBasicDto.Desc2;
detail.ItemName= itemBasicDto.Name;
detail.Uom = itemBasicDto.BasicUom;
}
}
return dictionary;
}
public override async Task<InjectionRequestDTO> HandleAsync(Guid id)
{
var entity=await _repository.GetAsync(id).ConfigureAwait(false);
await LocalEventBus.PublishAsync(new SfsHandledEntityEventData<InjectionRequest>(entity), false).ConfigureAwait(false);
return ObjectMapper.Map<InjectionRequest, InjectionRequestDTO>(entity);
}
#region 校验
private void CheckItemBasic(ItemBasicDTO ItemBasicDto, string itemCode)
{
if (ItemBasicDto == null)
{
throw new UserFriendlyException($"物品代码为【{itemCode}】不存在");
}
}
private void CheckLocation(LocationDTO LocationDto, string LocationCode)
{
if (LocationDto == null)
{
throw new UserFriendlyException($"库位代码为【{LocationCode}】不存在");
}
if (LocationDto.Type != EnumLocationType.WIP)
{
throw new UserFriendlyException($"库位代码【{LocationCode}】不是【{EnumLocationType.WIP.GetDisplayName()}】类型");
}
}
#endregion
#endregion
[HttpPost("")]
//[Authorize(InjectionRequestPermissions.Create)]
public override async Task<InjectionRequestDTO> CreateAsync(InjectionRequestEditInput input)
{
foreach (var item in input.Details)
{
if (item.Qty <= 0)
{
throw new UserFriendlyException($"{item.ItemCode} 物料的需求量必须大于 0");
}
}
//检验备料计划是否存在要料请求
if (!string.IsNullOrWhiteSpace(input.PreparationPlanNumber))
{
var exist = await CheckExistByPreparationPlanAsync(input.PreparationPlanNumber).ConfigureAwait(false);
if (exist.Count > 0)
{
throw new UserFriendlyException($"{input.PreparationPlanNumber} 备料计划已存在要料申请");
}
}
foreach (var item in input.Details) //赋值生产线
{
var location = await LocationAclService.GetByCodeAsync(item.ToLocationCode).ConfigureAwait(false);
item.ProdLine = location.LocationGroupCode;
input.ProdLine = location.LocationGroupCode;
}
var entity = ObjectMapper.Map<InjectionRequestEditInput, InjectionRequest>(input);
var result = await _injectionRequestManager.CreateAsync(entity).ConfigureAwait(false);
var dto = ObjectMapper.Map<InjectionRequest, InjectionRequestDTO>(result);
return dto;
}
/// <summary>
/// 创建并且执行叫料请求
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
/// <exception cref="UserFriendlyException"></exception>
[HttpPost("create-and-handle-api")]
//[Authorize(InjectionRequestPermissions.Create)]
public virtual async Task<InjectionRequestDTO> CreateAndHandleByAPIAsync(InjectionRequestEditInput input)
{
foreach (var item in input.Details)
{
if (item.Qty <= 0)
{
throw new UserFriendlyException($"{item.ItemCode} 物料的需求量必须大于 0");
}
}
input.AutoSubmit = true;
input.AutoAgree = true;
input.AutoHandle = true;
input.AutoCompleteJob = false;
input.DirectCreateNote = false;
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);
detailInput.ItemDesc1 = itemBasicDto.Desc1;
if(detailInput.PositionCode.Contains('W'))
{
detailInput.RecommendType = EnumRecommendType.W;
}
else if(detailInput.PositionCode.Contains('Q'))
{
detailInput.RecommendType = EnumRecommendType.Q;
}
else if(detailInput.PositionCode.Contains('K'))
{
detailInput.RecommendType = EnumRecommendType.K;
}
else
{
detailInput.RecommendType = EnumRecommendType.None;
}
var productionLineDto = await _productionLineAppService.GetByLocationGroupCodeAsync(toLocationDto.LocationGroupCode).ConfigureAwait(false);
detailInput.ToLocationCode = toLocationDto.ErpLocationCode;
if (productionLineDto != null)
{
detailInput.ProdLine = productionLineDto.Code;
}
}
var entity = ObjectMapper.Map<InjectionRequestEditInput, InjectionRequest>(input);
foreach (var detail in entity.Details)
{
var toLocationDto = await _locationAppService.GetByCodeAsync(detail.ToLocationCode).ConfigureAwait(false);
var productionLineDto = await _productionLineAppService.GetByLocationGroupCodeAsync(toLocationDto.LocationGroupCode).ConfigureAwait(false);
detail.ToLocationArea= toLocationDto.AreaCode;
detail.ToLocationErpCode = toLocationDto.ErpLocationCode;
detail.ToLocationGroup = toLocationDto.LocationGroupCode;
detail.ToWarehouseCode= toLocationDto.WarehouseCode;
}
entity.UseOnTheWayLocation = false;
var result = await _injectionRequestManager.CreateBynNumberAsync(entity).ConfigureAwait(false);
var dto = ObjectMapper.Map<InjectionRequest, InjectionRequestDTO>(result);
return dto;
}
/// <summary>
/// 创建并且执行叫料请求
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
/// <exception cref="UserFriendlyException"></exception>
[HttpPost("create-and-handle")]
//[Authorize(InjectionRequestPermissions.Create)]
public virtual async Task<InjectionRequestDTO> CreateAndHandleAsync(InjectionRequestEditInput input)
{
foreach (var item in input.Details)
{
if (item.Qty <= 0)
{
throw new UserFriendlyException($"{item.ItemCode} 物料的需求量必须大于0");
}
}
//检验备料计划是否存在要料请求
if (!string.IsNullOrWhiteSpace(input.PreparationPlanNumber))
{
var exist = await CheckExistByPreparationPlanAsync(input.PreparationPlanNumber).ConfigureAwait(false);
if (exist.Count > 0)
{
throw new UserFriendlyException($"{input.PreparationPlanNumber} 备料计划已存在要料申请");
}
}
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 location = await LocationAclService.GetByCodeAsync(detailInput.ToLocationCode).ConfigureAwait(false);
detailInput.ProdLine = location.LocationGroupCode;
input.ProdLine = location.LocationGroupCode;
input.Worker = input.Worker;
}
input.AutoSubmit = true;
input.AutoAgree = true;
input.AutoHandle = true;
input.AutoCompleteJob = false;
input.DirectCreateNote = false;
var entity = ObjectMapper.Map<InjectionRequestEditInput, InjectionRequest>(input);
var result = await _injectionRequestManager.CreateAsync(entity).ConfigureAwait(false);
var dto = ObjectMapper.Map<InjectionRequest, InjectionRequestDTO>(result);
return dto;
}
/// <summary>
/// 根据备料计划生成 叫料请求
/// </summary>
/// <returns></returns>
[HttpPost("create-and-handle-by-preparation-plan/{number}")]
public virtual async Task<InjectionRequestDTO> CreateAndHandleByPreparationPlan(string number)
{
var prodPreparationPlan = await _preparationPlanManager.GetByNumberAsync(number).ConfigureAwait(false);
var injectionRequestCreateInput = new InjectionRequestEditInput { Worker = CurrentUser.GetUserName() };
foreach (var preparationPlanDetail in prodPreparationPlan.Details)
{
var detail = new InjectionRequestDetailInput
{
ItemCode = preparationPlanDetail.ItemCode,
ItemName = preparationPlanDetail.ItemName,
ItemDesc1 = preparationPlanDetail.ItemDesc1,
ItemDesc2 = preparationPlanDetail.ItemDesc2,
Uom = preparationPlanDetail.Uom,
Qty = preparationPlanDetail.Qty,
StdPackQty = preparationPlanDetail.StdPackQty,
ToLocationCode = preparationPlanDetail.ToLocationCode
};
injectionRequestCreateInput.Details.Add(detail);
}
var dto = await CreateAndHandleAsync(injectionRequestCreateInput).ConfigureAwait(false);
return dto;
}
/// <summary>
/// 检验备料计划是否存在要料请求
/// </summary>
/// <param name="preparationPlanNumber"></param>
/// <returns></returns>
private async Task<List<InjectionRequest>> CheckExistByPreparationPlanAsync(string preparationPlanNumber)
{
var entities = await _repository.GetListAsync(c => c.PreparationPlanNumber == preparationPlanNumber)
.ConfigureAwait(false);
return entities;
}
/// <summary>
/// 根据类型获取叫料请求
/// </summary>
/// <param name="requestInput"></param>
/// <param name="type">
/// 叫料请求类型:
/// 人工拉动:Issue_Manual;
/// 线边拉动:Issue_WIP;
/// </param>
/// <param name="includeDetails"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpPost("by-type/{type}")]
public virtual async Task<PagedResultDto<InjectionRequestDTO>> GetListByTypeAsync(
SfsStoreRequestInputBase requestInput,
string type,
bool includeDetails = false,
CancellationToken cancellationToken = default)
{
Expression<Func<InjectionRequest, bool>> expression = p => p.Type == type;
if (requestInput.Condition.Filters?.Count > 0)
{
expression = expression.And(requestInput.Condition.Filters.ToLambda<InjectionRequest>());
}
return await GetPagedListAsync(expression, requestInput.SkipCount, requestInput.MaxResultCount,
requestInput.Sorting, includeDetails, cancellationToken).ConfigureAwait(false);
}
#region 导入
/// <summary>
/// 导入验证
/// </summary>
/// <param name="model"></param>
/// <param name="validationRresult"></param>
/// <returns></returns>
protected override async Task ValidateImportModelAsync(InjectionRequestImportInput model,
List<ValidationResult> validationRresult)
{
_ = new Dictionary<string, string>();
_ = await CheckItemBasicAsync(model, validationRresult).ConfigureAwait(false);
_ = await CheckLocationAsync(model, validationRresult).ConfigureAwait(false);
await CheckAreaAsync(model, validationRresult).ConfigureAwait(false);
await CheckStoreRelationAsync(model, validationRresult).ConfigureAwait(false);
}
#region 校验
protected override async Task<bool> ValidateImportEntities(Dictionary<InjectionRequest, EntityState> dict)
{
foreach (var entity in dict.Keys)
{
var tranType = await TransactionTypeAclService
.GetByTransTypeAsync(EnumTransType.Issue, EnumTransSubType.None).ConfigureAwait(false);
Check.NotNull(tranType, "事务类型", "事务类型不存在");
entity.AutoCompleteJob = tranType.AutoCompleteJob;
entity.AutoSubmit = tranType.AutoSubmitRequest;
entity.AutoAgree = tranType.AutoAgreeRequest;
entity.AutoHandle = tranType.AutoHandleRequest;
entity.DirectCreateNote = tranType.DirectCreateNote;
}
return await base.ValidateImportEntities(dict).ConfigureAwait(false);
}
protected async Task<ItemBasicDTO> CheckItemBasicAsync(InjectionRequestImportInput importInput,
List<ValidationResult> validationRresult)
{
var item = await _itemBasicAppService.GetByCodeAsync(importInput.ItemCode).ConfigureAwait(false);
if (item == null)
{
validationRresult.Add(new ValidationResult($"物品代码{importInput.ItemCode}不存在", new[] { "物品代码" }));
}
else if (item.StdPackQty == 0)
{
validationRresult.Add(
new ValidationResult($"物品代码{importInput.ItemCode}的物品信息中标准包装等于0或不存在", new[] { "标准包装" }));
}
return item;
}
protected async Task<LocationDTO> CheckLocationAsync(InjectionRequestImportInput importInput,
List<ValidationResult> validationRresult)
{
var location = await _locationAppService.GetByCodeAsync(importInput.ToLocationCode).ConfigureAwait(false);
if (location == null)
{
validationRresult.Add(new ValidationResult($"目标库位{importInput.ToLocationCode}不存在", new[] { "目标库位" }));
}
return location;
}
protected async Task CheckAreaAsync(InjectionRequestImportInput importInput,
List<ValidationResult> validationRresult)
{
var area = await _areaApp.GetByCodeAsync(importInput.FromLocationArea).ConfigureAwait(false);
if (area == null)
{
validationRresult.Add(new ValidationResult($"调出库区{importInput.FromLocationArea}不存在", new[] { "调出库区" }));
}
}
protected async Task CheckStoreRelationAsync(InjectionRequestImportInput importInput,
List<ValidationResult> validationRresult)
{
var itemStoreRelation = await _itemStoreRelationApp
.GetFirstAsync(importInput.ItemCode, importInput.ToLocationCode).ConfigureAwait(false);
if (itemStoreRelation == null)
{
validationRresult.Add(new ValidationResult(
$"物品代码{importInput.ItemCode}与目标库位{importInput.ToLocationCode}不存在对应关", new[] { "物品库位对应关系" }));
}
}
#endregion
#endregion
/// <summary>
/// 根据类型 获取叫料申请
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
[HttpGet("list/by-type/{type}")]
public virtual async Task<List<InjectionRequestDTO>> GetListByTypeAsync(string type)
{
var entities = await _repository.GetListAsync(c => c.Type == type).ConfigureAwait(false);
var dtos = ObjectMapper.Map<List<InjectionRequest>, List<InjectionRequestDTO>>(entities);
return dtos;
}
}

74
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Requests/InjectionRequests/InjectionRequestAutoMapperProfile.cs

@ -0,0 +1,74 @@
using AutoMapper;
using Volo.Abp.AutoMapper;
using Win_in.Sfs.Shared.Domain.Shared;
using Win_in.Sfs.Wms.Store.Application.Contracts;
using Win_in.Sfs.Wms.Store.Domain;
namespace Win_in.Sfs.Wms.Store.Application;
public partial class StoreApplicationAutoMapperProfile : Profile
{
private void InjectionRequestAutoMapperProfile()
{
CreateMap<InjectionRequest, InjectionRequestDTO>()
.ReverseMap();
CreateMap<InjectionRequestDetail, InjectionRequestDetailDTO>()
.ReverseMap();
CreateMap<InjectionRequestDetailInput, InjectionRequestDetail>()
.IgnoreAuditedObjectProperties()
.Ignore(x => x.ToLocationArea)
.Ignore(x => x.ToLocationGroup)
.Ignore(x => x.ToWarehouseCode)
.Ignore(x => x.MasterID)
.Ignore(x => x.TenantId)
.Ignore(x => x.Number)
.Ignore(x => x.Id);
CreateMap<InjectionRequestImportInput, InjectionRequest>()
.IgnoreAuditedObjectProperties()
.ForMember(x => x.Type, y => y.MapFrom(t => t.Type.ToString()))
.Ignore(x => x.PreparationPlanNumber)
.Ignore(x => x.ProdLine)
.Ignore(x => x.Workshop)
.Ignore(x => x.UseOnTheWayLocation)
.Ignore(x => x.Details)
.Ignore(x => x.Remark)
.Ignore(x => x.TenantId)
.Ignore(x => x.Number)
.Ignore(x => x.RequestStatus)
.Ignore(x => x.ConcurrencyStamp)
.Ignore(x => x.ExtraProperties)
.Ignore(x => x.ActiveDate)
.Ignore(x => x.Remark);
CreateMap<InjectionRequestImportInput, InjectionRequestDetail>()
.IgnoreAuditedObjectProperties()
.ForMember(x => x.Status, y => y.MapFrom(t => EnumStatus.Open))
.Ignore(x => x.ToLocationErpCode)
.Ignore(x => x.ToWarehouseCode)
.Ignore(x => x.ToLocationArea)
.Ignore(x => x.ToLocationGroup)
.Ignore(x => x.ItemName).Ignore(x => x.ItemDesc1).Ignore(x => x.ItemDesc2)
.Ignore(x => x.ProdLine)
.Ignore(x => x.WorkStation)
.Ignore(x => x.ExpiredTime)
.Ignore(x => x.IssuedQty)
.Ignore(x => x.ReceivedQty)
.Ignore(x => x.ToBeIssuedQty)
.Ignore(x => x.ToBeReceivedQty)
.Ignore(x => x.NotFinishQty)
.Ignore(x => x.StdPackQty)
.Ignore(x => x.Uom)
.Ignore(x => x.TenantId)
.Ignore(x => x.MasterID)
.Ignore(x => x.Number)
.Ignore(x => x.Id)
.Ignore(x => x.Remark);
CreateMap<InjectionRequestEditInput, InjectionRequest>()
.IgnoreAuditedObjectProperties()
.Ignore(x => x.RequestStatus)
.Ignore(x => x.ConcurrencyStamp).Ignore(x => x.Id);
}
}

2
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/StoreApplicationAutoMapperProfile.cs

@ -14,6 +14,7 @@ public partial class StoreApplicationAutoMapperProfile : Profile
InspectRequestAutoMapperProfile();
ItemTransformRequestAutoMapperProfile();
MaterialRequestAutoMapperProfile();
InjectionRequestAutoMapperProfile();
ProductionReturnRequestAutoMapperProfile();
ProductReceiptRequestAutoMapperProfile();
UnplannedIssueRequestAutoMapperProfile();
@ -60,6 +61,7 @@ public partial class StoreApplicationAutoMapperProfile : Profile
InventoryTransferNoteMapperProfile();
IsolationNoteAutoMapperProfile();
IssueNoteAutoMapperProfile();
InjectionNoteAutoMapperProfile();
ContainerNoteAutoMapperProfile();
ItemTransformNoteAutoMapperProfile();
JisDeliverNoteAutoMapperProfile();

6
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain.Shared/Settings/StoreSettings.cs

@ -112,6 +112,12 @@ public static class StoreSettings
public const string EnableMultipleCreateIssueJob = $"{Default}.{nameof(EnableMultipleCreateIssueJob)}";
}
public static class InjectionRequest
{
private const string Default = $"{GroupName}.{nameof(InjectionRequest)}";
public const string EnableMultipleCreateInjectionJob = $"{Default}.{nameof(EnableMultipleCreateInjectionJob)}";
}
public static class Cache
{

10
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/InjectionJobs/IInjectionJobManager.cs

@ -0,0 +1,10 @@
using System;
using System.Linq.Expressions;
using System.Threading.Tasks;
namespace Win_in.Sfs.Wms.Store.Domain;
public interface IInjectionJobManager : IJobManager<InjectionJob>
{
Task<InjectionJob> GetAsync(Expression<Func<InjectionJob, bool>> expression);
}

6
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/InjectionJobs/IInjectionJobRepository.cs

@ -0,0 +1,6 @@
namespace Win_in.Sfs.Wms.Store.Domain;
public interface IIssueJobRepository : ISfsJobRepositoryBase<IssueJob>
{
}

84
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/InjectionJobs/InjectionJob.cs

@ -0,0 +1,84 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Threading.Tasks;
using Win_in.Sfs.Shared.Domain.Entities;
namespace Win_in.Sfs.Wms.Store.Domain;
/// <summary>
/// 注塑发料任务
/// </summary>
[Display(Name = "注塑发料任务")]
public class InjectionJob : SfsJobAggregateRootBase<InjectionJobDetail>
{
/// <summary>
/// 叫料请求类型
/// </summary>
[IgnoreUpdate]
public string RequestType { get; set; }
/// <summary>
/// 生产线
/// </summary>
[IgnoreUpdate]
public string ProdLine { get; set; }
/// <summary>
/// 要货单号
/// </summary>
[IgnoreUpdate]
public string InjectionRequestNumber { get; set; }
/// <summary>
/// 车间
/// </summary>
[IgnoreUpdate]
public string Workshop { get; set; }
/// <summary>
/// 使用在途库
/// </summary>
[Display(Name = "使用在途库")]
[IgnoreUpdate]
public bool UseOnTheWayLocation { get; set; }
/// <summary>
/// 任务明细
/// </summary>
[IgnoreUpdate]
public override List<InjectionJobDetail> Details { get; set; } = new List<InjectionJobDetail>();
/// <summary>
/// 设置任务明细的实际库位和实际数量
/// </summary>
/// <param name="id"></param>
/// <param name="handledLocationCode"></param>
/// <param name="handledLocationErpCode"></param>
/// <param name="handledWarehouseCode"></param>
/// <param name="handledQty"></param>
/// <param name="handledBatch"></param>
/// <param name="handledContainerCode"></param>
/// <param name="handledLot"></param>
/// <param name="handledPackingCode"></param>
/// <returns></returns>
public virtual async Task BuildDetail(Guid id, string handledLocationCode, string handledLocationErpCode,
string handledWarehouseCode, decimal handledQty, string handledSupplierBatch, DateTime handledArriveDate, DateTime handledProduceDate, DateTime handledExpireDate,
string handledContainerCode, string handledLot, string handledPackingCode)
{
var detail = GetDetail(id);
detail.HandledFromLocationCode = handledLocationCode;
detail.HandledFromLocationErpCode = handledLocationErpCode;
detail.HandledFromWarehouseCode = handledWarehouseCode;
detail.HandledQty = handledQty;
detail.HandledSupplierBatch = handledSupplierBatch;
detail.HandledArriveDate = handledArriveDate;
detail.HandledProduceDate = handledProduceDate;
detail.HandledExpireDate = handledExpireDate;
detail.HandledContainerCode = handledContainerCode;
detail.HandledLot = handledLot;
detail.HandledPackingCode = handledPackingCode;
await Task.CompletedTask.ConfigureAwait(false);
}
}

108
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/InjectionJobs/InjectionJobDetail.cs

@ -0,0 +1,108 @@
using System;
using Win_in.Sfs.Shared.Domain;
using Win_in.Sfs.Shared.Domain.Shared;
namespace Win_in.Sfs.Wms.Store.Domain;
public class InjectionJobDetail : SfsJobRecommendFromDetailEntityBase, IHasToLocation
{
/// <summary>
/// 请求库位
/// </summary>
public string RequestLocationCode { get; set; }
/// <summary>
/// 到库位
/// </summary>
public string ToLocationCode { get; set; }
/// <summary>
/// 到库区
/// </summary>
public string ToLocationArea { get; set; }
/// <summary>
/// 到库位组
/// </summary>
public string ToLocationGroup { get; set; }
/// <summary>
/// 到ERP库位
/// </summary>
public string ToLocationErpCode { get; set; }
/// <summary>
/// 到仓库
/// </summary>
public string ToWarehouseCode { get; set; }
/// <summary>
/// 在途库库位
/// </summary>
public string OnTheWayLocationCode { get; set; }
/// <summary>
/// 生产线
/// </summary>
public string ProdLine { get; set; }
/// <summary>
/// 工作中心
/// </summary>
public string WorkStation { get; set; }
/// <summary>
/// 过期时间
/// </summary>
public DateTime ExpiredTime { get; set; }
/// <summary>
/// 工序
/// </summary>
public string Operation { get; set; }
/// <summary>
/// 配送方式
/// </summary>
public EnumDistributionType DistributionType { get; set; }
/// <summary>
/// 取整方式
/// </summary>
public EnumTruncType TruncType { get; set; }
/// <summary>
/// 取整后数量
/// </summary>
public decimal RoundedQty { get; set; }
/// <summary>
/// 计划拆分规则
/// </summary>
public EnumPlannedSplitRule PlannedSplitRule { get; set; }
/// <summary>
/// 计划开始时间
/// </summary>
public DateTime PlanBeginTime { get; set; }
/// <summary>
/// 每次配送数量
/// </summary>
public decimal DeliveryQty { get; set; }
/// <summary>
/// 位置码
/// </summary>
public string PositionCode { get; set; }
/// <summary>
/// 推荐类型
/// </summary>
public EnumRecommendType RecommendType { get; set; }
public void SetId(Guid id)
{
this.Id = id;
}
}

82
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/InjectionJobs/InjectionJobManager.cs

@ -0,0 +1,82 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
using Volo.Abp.Users;
using Volo.Abp.Validation;
using Win_in.Sfs.Shared.Domain.Shared;
namespace Win_in.Sfs.Wms.Store.Domain;
public class InjectionJobManager : SfsJobManagerBase<InjectionJob, InjectionJobDetail>, IInjectionJobManager
{
public InjectionJobManager(
IInjectionJobRepository repository
) : base(repository)
{
}
/// <summary>
/// 执行任务 发料任务
/// </summary>
/// <param name="id"></param>
/// <param name="input"></param>
/// <param name="user"></param>
/// <returns></returns>
public override async Task<InjectionJob> CompleteAsync(InjectionJob input, ICurrentUser user)
{
var entity = await Repository.FindAsync(input.Id).ConfigureAwait(false);
foreach (var detail in input.Details)
{
//发料子任务 赋值实际转移
await entity.BuildDetail(detail.Id,
detail.HandledFromLocationCode,
detail.HandledFromLocationErpCode,
detail.HandledFromWarehouseCode,
detail.HandledQty,
detail.HandledSupplierBatch,
detail.HandledArriveDate,
detail.HandledProduceDate,
detail.HandledExpireDate,
detail.HandledContainerCode,
detail.HandledLot,
detail.HandledPackingCode).ConfigureAwait(false);
}
return await base.CompleteAsync(entity, user).ConfigureAwait(false);
}
public override void CheckDetails(InjectionJob entity, AbpValidationResult result)
{
var details = entity.Details;
foreach (var detail in details)
{
if (detail.HandledFromLocationCode == null)
{
result.Errors.Add(new ValidationResult($"{detail.HandledFromLocationCode} 不能为空"));
}
}
}
public override async Task<List<InjectionJob>> GetWorkingListByPackingAsync(string packingCode)
{
return await Repository.GetListAsync(c => c.Details.Any(p => p.RecommendPackingCode == packingCode) && c.JobStatus != EnumJobStatus.Closed && c.JobStatus != EnumJobStatus.Cancelled, true).ConfigureAwait(false);
}
public override async Task<List<InjectionJob>> GetWorkingListByContainerAsync(string containerCode)
{
return await Repository.GetListAsync(c => c.Details.Any(p => p.RecommendContainerCode == containerCode) && c.JobStatus != EnumJobStatus.Closed && c.JobStatus != EnumJobStatus.Cancelled, true).ConfigureAwait(false);
}
public async Task<InjectionJob> GetAsync(Expression<Func<InjectionJob, bool>> expression)
{
return await Repository.FindAsync(expression).ConfigureAwait(false);
}
}

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

@ -1,6 +1,6 @@
namespace Win_in.Sfs.Wms.Store.Domain;
public interface IIssueJobRepository : ISfsJobRepositoryBase<IssueJob>
public interface IInjectionJobRepository : ISfsJobRepositoryBase<InjectionJob>
{
}

10
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Notes/InjectionNotes/IInjectionNoteManager.cs

@ -0,0 +1,10 @@
using System;
using System.Threading.Tasks;
namespace Win_in.Sfs.Wms.Store.Domain;
public interface IInjectionNoteManager : ISfsStoreManager<InjectionNote, InjectionNoteDetail>
{
Task<InjectionNote> ConfirmAsync(Guid id);
}

6
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Notes/InjectionNotes/IInjectionNoteRepository.cs

@ -0,0 +1,6 @@
namespace Win_in.Sfs.Wms.Store.Domain;
public interface IInjectionNoteRepository : ISfsStoreRepositoryBase<InjectionNote>
{
}

77
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Notes/InjectionNotes/InjectionNote.cs

@ -0,0 +1,77 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using Volo.Abp;
using Win_in.Sfs.Shared.Domain.Entities;
namespace Win_in.Sfs.Wms.Store.Domain;
/// <summary>
/// 注塑发料记录
/// </summary>
public class InjectionNote : SfsStoreAggregateRootBase<InjectionNoteDetail>, IHasJobNumber, IHasRequestNumber
{
/// <summary>
/// 任务ID
/// </summary>
[IgnoreUpdate]
public string JobNumber { get; set; }
/// <summary>
/// 车间
/// </summary>
[IgnoreUpdate]
public string Workshop { get; set; }
/// <summary>
/// 明细列表
/// </summary>
[IgnoreUpdate]
public override List<InjectionNoteDetail> Details { get; set; } = new List<InjectionNoteDetail>();
[IgnoreUpdate]
public string RequestNumber { get; set; }
/// <summary>
/// 叫料请求类型
/// </summary>
[IgnoreUpdate]
public string RequestType { get; set; }
/// <summary>
/// 使用在途库
/// </summary>
[IgnoreUpdate]
public bool UseOnTheWayLocation { get; set; }
/// <summary>
/// 确认时间
/// </summary>
[Display(Name = "确认时间")]
[IgnoreUpdate]
public DateTime? ConfirmTime { get; set; }
/// <summary>
/// 已确认
/// </summary>
[Display(Name = "已确认")]
public bool Confirmed { get; set; }
public void Confirm(DateTime confirmTime)
{
CheckStatus(Confirmed);
Confirmed = true;
ConfirmTime = confirmTime;
}
private static void CheckStatus(bool confirmed)
{
if (confirmed)
{
throw new UserFriendlyException($"当前状态为 【已确认】 ,无法再次确认!");
}
}
}

43
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Notes/InjectionNotes/InjectionNoteDetail.cs

@ -0,0 +1,43 @@
using System;
using Win_in.Sfs.Shared.Domain.Shared;
namespace Win_in.Sfs.Wms.Store.Domain;
public class InjectionNoteDetail : SfsStoreRecommendFromDetailWithFromToEntityBase
{
/// <summary>
/// 发料时间
/// </summary>
public DateTime IssueTime { get; set; }
/// <summary>
/// 过期时间
/// </summary>
public DateTime ExpiredTime { get; set; }
/// <summary>
/// 生产线
/// </summary>
public string ProdLine { get; set; }
/// <summary>
/// 工作中心
/// </summary>
public string WorkStation { get; set; }
/// <summary>
/// 在途库库位
/// </summary>
public string OnTheWayLocationCode { get; set; }
/// <summary>
/// 位置码
/// </summary>
public string PositionCode { get; set; }
/// <summary>
/// 推荐类型
/// </summary>
public EnumRecommendType RecommendType { get; set; }
}

42
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Notes/InjectionNotes/InjectionNoteManager.cs

@ -0,0 +1,42 @@
using System;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Volo.Abp;
using Volo.Abp.Uow;
using Win_in.Sfs.Shared.Event;
namespace Win_in.Sfs.Wms.Store.Domain;
public class InjectionNoteManager : SfsStoreManagerBase<InjectionNote, InjectionNoteDetail>, IInjectionNoteManager
{
public InjectionNoteManager(
IInjectionNoteRepository repository
) : base(repository)
{
}
[UnitOfWork]
public virtual async Task<InjectionNote> ConfirmAsync(Guid id)
{
var entity = await Repository.FindAsync(id).ConfigureAwait(false);
Check.NotNull(entity, EntityClassName);
entity.Confirm(Clock.Now);
await PublishConfirmedAsync(entity).ConfigureAwait(false);
return await Repository.UpdateAsync(entity).ConfigureAwait(false);
}
private async Task PublishConfirmedAsync(InjectionNote entity)
{
try
{
await LocalEventBus.PublishAsync(new SfsConfirmedEntityEventData<InjectionNote>(entity), false).ConfigureAwait(false);
}
catch (Exception ex)
{
Logger.LogDebug($"{nameof(InjectionNote)} Confirmed Event:{ex.Message}", null);
Console.WriteLine(ex.Source);
throw;
}
}
}

16
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/InjectionRequests/IInjectionRequestManager.cs

@ -0,0 +1,16 @@
using System.Threading.Tasks;
namespace Win_in.Sfs.Wms.Store.Domain;
using Win_in.Sfs.Shared.Domain;
public interface IInjectionRequestManager : ISfsStoreRequestManager<InjectionRequest, InjectionRequestDetail>,
IBulkImportService<InjectionRequest>
{
Task UpdateDetailsAsync(InjectionRequest entity);
Task CompleteAsync(string number);
Task<InjectionRequest> CreateBynNumberAsync(InjectionRequest entity);
}

9
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/InjectionRequests/IInjectionRequestRepository.cs

@ -0,0 +1,9 @@
using Win_in.Sfs.Shared.Domain;
namespace Win_in.Sfs.Wms.Store.Domain;
public interface IInjectionRequestRepository : ISfsStoreRepositoryBase<InjectionRequest>,
ISfsBulkRepositoryBase<InjectionRequest>
{
}

47
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/InjectionRequests/InjectionRequest.cs

@ -0,0 +1,47 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using Win_in.Sfs.Shared.Domain.Entities;
namespace Win_in.Sfs.Wms.Store.Domain;
/// <summary>
/// 注塑申请
/// </summary>
public class InjectionRequest : SfsStoreRequestAggregateRootBase<InjectionRequestDetail>
{
/// <summary>
/// 叫料类型
/// </summary>
[Display(Name = "叫料类型")]
[IgnoreUpdate]
public string Type { get; set; }
/// <summary>
/// 备料计划单号
/// </summary>
[IgnoreUpdate]
public string PreparationPlanNumber { get; set; }
/// <summary>
/// 生产线
/// </summary>
[IgnoreUpdate]
public string ProdLine { get; set; }
/// <summary>
/// 车间
/// </summary>
[IgnoreUpdate]
public string Workshop { get; set; }
/// <summary>
/// 使用在途库
/// </summary>
public bool UseOnTheWayLocation { get; set; }
/// <summary>
/// 明细列表
/// </summary>
[IgnoreUpdate]
public override List<InjectionRequestDetail> Details { get; set; } = new List<InjectionRequestDetail>();
}

105
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/InjectionRequests/InjectionRequestDetail.cs

@ -0,0 +1,105 @@
using System;
using System.ComponentModel.DataAnnotations.Schema;
using Win_in.Sfs.Shared.Domain;
using Win_in.Sfs.Shared.Domain.Shared;
namespace Win_in.Sfs.Wms.Store.Domain;
/// <summary>
/// 注塑申请明细
/// </summary>
public class InjectionRequestDetail : SfsStoreDetailWithQtyEntityBase, IHasToLocation
{
/// <summary>
/// 到库位
/// </summary>
public string ToLocationCode { get; set; }
/// <summary>
/// 到库区
/// </summary>
public string ToLocationArea { get; set; }
/// <summary>
/// 到库位组
/// </summary>
public string ToLocationGroup { get; set; }
/// <summary>
/// 到ERP库位
/// </summary>
public string ToLocationErpCode { get; set; }
/// <summary>
/// 到仓库
/// </summary>
public string ToWarehouseCode { get; set; }
/// <summary>
/// 来源库区
/// </summary>
public string FromLocationArea { get; set; }
// /// <summary>
// /// 在途库库位
// /// </summary>
// public string OnTheWayLocationCode { get; set; }
/// <summary>
/// 生产线
/// </summary>
public string ProdLine { get; set; }
/// <summary>
/// 工作中心
/// </summary>
public string WorkStation { get; set; }
/// <summary>
/// 过期时间
/// </summary>
public DateTime ExpiredTime { get; set; }
/// <summary>
/// 已发数量
/// </summary>
public decimal IssuedQty { get; set; }
/// <summary>
/// 已收数量
/// </summary>
public decimal ReceivedQty { get; set; }
/// <summary>
/// 明细状态
/// </summary>
public EnumStatus Status { get; set; }
/// <summary>
/// 请求未发 还未发送的数量
/// </summary>
[NotMapped]
public decimal ToBeIssuedQty => Qty - IssuedQty;
/// <summary>
/// 已发未收
/// </summary>
[NotMapped]
public decimal ToBeReceivedQty => IssuedQty - ReceivedQty;
/// <summary>
/// 请求未收
/// </summary>
[NotMapped]
public decimal NotFinishQty => Qty - ReceivedQty;
/// <summary>
/// 位置码
/// </summary>
public string PositionCode { get; set; }
/// <summary>
/// 推荐类型
/// </summary>
public EnumRecommendType RecommendType { get; set; }
}

141
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/InjectionRequests/InjectionRequestManager.cs

@ -0,0 +1,141 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using DocumentFormat.OpenXml.Math;
using Win_in.Sfs.Shared.Domain.Shared;
using Win_in.Sfs.Shared.Event;
using static Win_in.Sfs.Wms.Store.Domain.Shared.StoreSettings;
namespace Win_in.Sfs.Wms.Store.Domain;
public class InjectionRequestManager
: SfsStoreRequestManagerBase<InjectionRequest, InjectionRequestDetail>
, IInjectionRequestManager
{
private readonly IInjectionRequestRepository _repository;
private readonly IIssueJobRepository _issueJobRepository;
public InjectionRequestManager(
IInjectionRequestRepository repository
, IIssueJobRepository issueJobRepository
) : base(repository)
{
_repository = repository;
_issueJobRepository = issueJobRepository;
}
/// <summary>
/// 创建
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
public virtual async Task<InjectionRequest> CreateBynNumberAsync(InjectionRequest entity)
{
var number = string.IsNullOrEmpty(entity.Number) ? await GenerateNumberAsync(nameof(InjectionRequest), entity.ActiveDate).ConfigureAwait(false) : entity.Number;
entity.SetIdAndNumberWithDetails(GuidGenerator, number);
entity.Submit();
entity.Agree();
entity.RequestStatus = EnumRequestStatus.Partial;
await LocalEventBus.PublishAsync(new SfsHandledEntityEventData<InjectionRequest>(entity), false)
.ConfigureAwait(false);
await _repository.InsertAsync(entity).ConfigureAwait(false);
return entity;
}
public virtual async Task UpdateDetailsAsync(InjectionRequest newEntity)
{
var oldEntity = await Repository.FindAsync(newEntity.Id, true).ConfigureAwait(false);
if(oldEntity!=null)
{
foreach (var newDetail in newEntity.Details)
{
oldEntity.ReplaceDetail(newDetail.Id, newDetail);
}
foreach (var detail in oldEntity.Details)
{
SetMaterialRequestDetailStatus(detail);
}
await SetMaterialRequestStatus(oldEntity).ConfigureAwait(false);
await Repository.UpdateAsync(oldEntity).ConfigureAwait(false);
}
}
private void SetMaterialRequestDetailStatus(InjectionRequestDetail detail)
{
if (detail.ReceivedQty >= detail.Qty)//执行的时候 实际收料 多余 要料数
{
detail.Status = EnumStatus.Close;
}
else
{
detail.Status = EnumStatus.Open;
}
}
private async Task SetMaterialRequestStatus(InjectionRequest materialRequest)
{
if (materialRequest.Details.All(p => p.Status == EnumStatus.Close))
{
materialRequest.RequestStatus = EnumRequestStatus.Completed;
}
else
{
var issueJobs = await _issueJobRepository.GetListAsync(t => t.MaterialRequestNumber == materialRequest.Number).ConfigureAwait(false);
if (issueJobs.Count > 0)
{
if (issueJobs.All(t => t.JobStatus is EnumJobStatus.Done or EnumJobStatus.Closed or EnumJobStatus.Cancelled))
{
if (materialRequest.Details.All(p => p.ReceivedQty >= p.Qty))
{
materialRequest.RequestStatus = EnumRequestStatus.Completed;
}
else
{
materialRequest.RequestStatus = EnumRequestStatus.Partial;
}
}
else
{
materialRequest.RequestStatus = EnumRequestStatus.Partial;
}
}
else
{
materialRequest.RequestStatus = EnumRequestStatus.Partial;
}
}
}
public virtual async Task CompleteAsync(string number)
{
var entity = await GetByNumberAsync(number).ConfigureAwait(false);
if (entity != null && !entity.Details.Any(p => p.ToBeIssuedQty > 0))
{
await CompleteAsync(entity).ConfigureAwait(false);
}
}
#region 导入
/// <summary>
/// 执行导入
/// </summary>
public virtual async Task ImportDataAsync(List<InjectionRequest> mergeEntities, List<InjectionRequest> deleteEntities = null)
{
if (deleteEntities != null && deleteEntities.Count > 0)
{
await _repository.BulkDeleteAsync(deleteEntities).ConfigureAwait(false);
}
await CreateManyAsync(mergeEntities).ConfigureAwait(false);
}
#endregion
}

3
be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/IStoreDbContext.cs

@ -18,6 +18,7 @@ public interface IStoreDbContext : IEfCoreDbContext
public DbSet<TransferRequest> TransferRequests { get; }
public DbSet<ProductReceiptRequest> ProductReceiptRequests { get; }
public DbSet<MaterialRequest> MaterialRequests { get; }
public DbSet<InjectionRequest> InjectionRequests { get; }
public DbSet<ContainerRequest> ContainerRequests { get; }
public DbSet<DeliverRequest> DeliverRequests { get; }
public DbSet<InspectRequest> InspectRequests { get; }
@ -69,6 +70,7 @@ public interface IStoreDbContext : IEfCoreDbContext
public DbSet<InventoryTransferNote> InventoryTransferNotes { get; }
public DbSet<WarehouseTransferNote> WarehouseTransferNotes { get; }
public DbSet<IssueNote> IssueNotes { get; }
public DbSet<InjectionNote> InjectionNotes { get; }
public DbSet<ContainerNote> ContainerNotes { get; }
public DbSet<UnplannedReceiptNote> UnplannedReceiptNotes { get; }
public DbSet<UnplannedIssueNote> UnplannedIssueNotes { get; }
@ -94,6 +96,7 @@ public interface IStoreDbContext : IEfCoreDbContext
public DbSet<InspectJob> InspectJobs { get; }
public DbSet<PutawayJob> PutawayJobs { get; }
public DbSet<IssueJob> IssueJobs { get; }
public DbSet<InjectionJob> InjectionJobs { get; }
public DbSet<ContainerJob> ContainerJobs { get; }
public DbSet<DeliverJob> DeliverJobs { get; }
public DbSet<JisDeliverJob> JisDeliverJobs { get; }

69
be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Jobs/InjectionJobs/InjectionJobDbContextModelCreatingExtensions.cs

@ -0,0 +1,69 @@
using Microsoft.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore.Modeling;
using Win_in.Sfs.Shared.Domain.Shared;
using Win_in.Sfs.Shared.EntityFrameworkCore;
using Win_in.Sfs.Wms.Store.Domain;
namespace Win_in.Sfs.Wms.Store.EntityFrameworkCore;
public static class InjectionJobDbContextModelCreatingExtensions
{
public static void ConfigureInjectionJob(this ModelBuilder builder, StoreModelBuilderConfigurationOptions options)
{
builder.Entity<InjectionJob>(b =>
{
//Configure table & schema name
b.ToTable(StoreDbProperties.JobDbTablePrefix + nameof(InjectionJob), options.Schema);
//Configure ABP properties
b.ConfigureByConvention();
//Configure Sfs base properties
b.ConfigureSfsBase();
//Configure Job base properties
b.ConfigureJob<InjectionJob, InjectionJobDetail>();
//Properties
b.Property(q => q.RequestType).HasMaxLength(SfsPropertyConst.CodeLength);
b.Property(q => q.InjectionRequestNumber).HasMaxLength(SfsPropertyConst.CodeLength);
b.Property(q => q.Workshop).HasMaxLength(SfsPropertyConst.CodeLength);
b.Property(q => q.ProdLine).HasMaxLength(SfsPropertyConst.CodeLength);
//Relations
b.HasMany(q => q.Details).WithOne().HasForeignKey(d => d.MasterID).IsRequired();
//Indexes
b.HasIndex(q => new { q.Number }).IsUnique();
});
builder.Entity<InjectionJobDetail>(b =>
{
//Configure table & schema name
b.ToTable(StoreDbProperties.JobDbTablePrefix + nameof(InjectionJobDetail), options.Schema);
//Configure ABP properties
b.ConfigureByConvention();
//Configure Sfs base properties
b.ConfigureSfsBase();
//Configure Job base properties
b.ConfigureJobRecommendFromDetail();
//Properties
b.Property(q => q.ExpiredTime).IsRequired();
b.Property(q => q.ToLocationCode).HasMaxLength(SfsPropertyConst.CodeLength);
b.Property(q => q.ToLocationErpCode).HasMaxLength(SfsPropertyConst.CodeLength);
b.Property(q => q.ToWarehouseCode).HasMaxLength(SfsPropertyConst.CodeLength);
b.Property(q => q.ToLocationArea).HasMaxLength(SfsPropertyConst.CodeLength);
b.Property(q => q.ToLocationGroup).HasMaxLength(SfsPropertyConst.CodeLength);
b.Property(q => q.RequestLocationCode).HasMaxLength(SfsPropertyConst.CodeLength);
b.Property(q => q.ProdLine).HasMaxLength(SfsPropertyConst.CodeLength);
b.Property(q => q.WorkStation).HasMaxLength(SfsPropertyConst.CodeLength);
b.Property(q => q.Operation).HasMaxLength(SfsPropertyConst.CodeLength);
b.Property(q => q.DistributionType).HasMaxLength(SfsPropertyConst.NameLength).HasConversion<string>();
b.Property(q => q.TruncType).HasMaxLength(SfsPropertyConst.NameLength).HasConversion<string>();
b.Property(q => q.PlannedSplitRule).HasMaxLength(SfsPropertyConst.NameLength).HasConversion<string>();
b.Property(q => q.OnTheWayLocationCode).HasMaxLength(SfsPropertyConst.CodeLength);
b.Property(q => q.PositionCode).HasMaxLength(SfsPropertyConst.CodeLength);
b.Property(q => q.RecommendType).HasMaxLength(SfsPropertyConst.CodeLength).HasConversion<string>();
//Relations
//None
//Indexes
//b.HasIndex(q => new { q.PackingCode }).IsUnique();
});
}
}

11
be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Jobs/InjectionJobs/InjectionJobEfCoreRepository.cs

@ -0,0 +1,11 @@
using Volo.Abp.EntityFrameworkCore;
using Win_in.Sfs.Wms.Store.Domain;
namespace Win_in.Sfs.Wms.Store.EntityFrameworkCore;
public class InjectionJobEfCoreRepository : SfsJobEfCoreRepositoryBase<StoreDbContext, InjectionJob>, IInjectionJobRepository
{
public InjectionJobEfCoreRepository(IDbContextProvider<StoreDbContext> dbContextProvider) : base(dbContextProvider)
{
}
}

63
be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Notes/InjectionNotes/InjectionNoteDbContextModelCreatingExtensions.cs

@ -0,0 +1,63 @@
using Microsoft.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore.Modeling;
using Win_in.Sfs.Shared.Domain.Shared;
using Win_in.Sfs.Wms.Store.Domain;
namespace Win_in.Sfs.Wms.Store.EntityFrameworkCore;
public static class InjectionNoteDbContextModelCreatingExtensions
{
public static void ConfigureInjectionNote(this ModelBuilder builder, StoreModelBuilderConfigurationOptions options)
{
builder.Entity<InjectionNote>(b =>
{
//Configure table & schema name
b.ToTable(options.TablePrefix + nameof(InjectionNote), options.Schema);
//Configure ABP properties
b.ConfigureByConvention();
//Configure Sfs base properties
b.ConfigureSfsStoreBase();
//Properties
b.Property(q => q.RequestNumber).HasMaxLength(SfsPropertyConst.CodeLength);
b.Property(q => q.RequestType).HasMaxLength(SfsPropertyConst.CodeLength);
b.Property(q => q.Workshop).HasMaxLength(SfsPropertyConst.NameLength);
b.Property(q => q.Remark).HasMaxLength(SfsPropertyConst.RemarkLength);
//Relations
b.HasMany(q => q.Details).WithOne().HasForeignKey(d => d.MasterID).IsRequired();
//Indexes
b.HasIndex(q => new { q.Number }).IsUnique();
});
builder.Entity<InjectionNoteDetail>(b =>
{
//Configure table & schema name
b.ToTable(options.TablePrefix + nameof(InjectionNoteDetail), options.Schema);
//Configure ABP properties
b.ConfigureByConvention();
//Configure Sfs base properties
b.ConfigureSfsStoreBase();
//Configure Sfs store detail properties
b.ConfigureSfsStoreDetailBase();
//Properties
b.Property(q => q.IssueTime).IsRequired();
b.Property(q => q.ExpiredTime).IsRequired();
b.Property(q => q.ProdLine).HasMaxLength(SfsPropertyConst.NameLength);
b.Property(q => q.WorkStation).HasMaxLength(SfsPropertyConst.NameLength);
b.Property(q => q.OnTheWayLocationCode).HasMaxLength(SfsPropertyConst.CodeLength);
b.Property(q => q.FromStatus).HasMaxLength(SfsPropertyConst.NameLength).HasConversion<string>();
b.Property(q => q.ToStatus).HasMaxLength(SfsPropertyConst.NameLength).HasConversion<string>();
b.Property(q => q.PositionCode).HasMaxLength(SfsPropertyConst.CodeLength);
b.Property(q => q.RecommendType).HasMaxLength(SfsPropertyConst.NameLength).HasConversion<string>();
//Relations
//Indexes
b.HasIndex(q => new { q.Number, q.FromPackingCode, q.FromLocationCode, q.ToLocationCode }).IsUnique();
b.HasIndex(q => new { q.FromPackingCode });
});
}
}

11
be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Notes/InjectionNotes/InjectionNoteEfCoreRepository.cs

@ -0,0 +1,11 @@
using Volo.Abp.EntityFrameworkCore;
using Win_in.Sfs.Wms.Store.Domain;
namespace Win_in.Sfs.Wms.Store.EntityFrameworkCore;
public class InjectionNoteEfCoreRepository : SfsStoreEfCoreRepositoryBase<StoreDbContext, InjectionNote>, IInjectionNoteRepository
{
public InjectionNoteEfCoreRepository(IDbContextProvider<StoreDbContext> dbContextProvider) : base(dbContextProvider)
{
}
}

67
be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Requests/InjectionRequests/InjectionRequestDbContextModelCreatingExtensions.cs

@ -0,0 +1,67 @@
using Microsoft.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore.Modeling;
using Win_in.Sfs.Shared.Domain.Shared;
using Win_in.Sfs.Wms.Store.Domain;
namespace Win_in.Sfs.Wms.Store.EntityFrameworkCore;
public static class InjectionRequestDbContextModelCreatingExtensions
{
public static void ConfigureInjectionRequest(this ModelBuilder builder, StoreModelBuilderConfigurationOptions options)
{
builder.Entity<InjectionRequest>(b =>
{
//Configure table & schema name
b.ToTable(options.TablePrefix + nameof(InjectionRequest), options.Schema);
//Configure ABP properties
b.ConfigureByConvention();
//Configure Sfs base properties
b.ConfigureSfsStoreBase();
//Properties
b.Property(q => q.Type).HasMaxLength(SfsPropertyConst.CodeLength);
b.Property(q => q.PreparationPlanNumber).HasMaxLength(SfsPropertyConst.CodeLength);
b.Property(q => q.ProdLine).HasMaxLength(SfsPropertyConst.CodeLength);
b.Property(q => q.Workshop).HasMaxLength(SfsPropertyConst.CodeLength);
b.Property(q => q.RequestStatus).HasMaxLength(SfsPropertyConst.NameLength).HasConversion<string>();
//Relations
b.HasMany(q => q.Details).WithOne().HasForeignKey(d => d.MasterID).IsRequired();
//Indexes
b.HasIndex(q => new { q.Number }).IsUnique();
});
builder.Entity<InjectionRequestDetail>(b =>
{
//Configure table & schema name
b.ToTable(options.TablePrefix + nameof(InjectionRequestDetail), options.Schema);
//Configure ABP properties
b.ConfigureByConvention();
//Configure Sfs base properties
b.ConfigureSfsStoreBase();
//Configure Sfs store detail properties
b.ConfigureSfsStoreDetailBase();
//Properties
b.Property(q => q.ToLocationCode).IsRequired().HasMaxLength(SfsPropertyConst.CodeLength);
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.ExpiredTime).IsRequired();
b.Property(q => q.ProdLine).HasMaxLength(SfsPropertyConst.CodeLength);
b.Property(q => q.WorkStation).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>();
b.Property(q => q.PositionCode).HasMaxLength(SfsPropertyConst.CodeLength);
b.Property(q => q.RecommendType).HasMaxLength(SfsPropertyConst.NameLength).HasConversion<string>();
//Relations
//Indexes
b.HasIndex(q => new { q.Number, q.ItemCode, q.ToLocationCode }).IsUnique();
b.HasIndex(q => new { q.ItemCode });
});
}
}

11
be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/Requests/InjectionRequests/InjectionRequestEfCoreRepository.cs

@ -0,0 +1,11 @@
using Volo.Abp.EntityFrameworkCore;
using Win_in.Sfs.Wms.Store.Domain;
namespace Win_in.Sfs.Wms.Store.EntityFrameworkCore;
public class InjectionRequestEfCoreRepository : SfsStoreEfCoreRepositoryBase<StoreDbContext, InjectionRequest>, IInjectionRequestRepository
{
public InjectionRequestEfCoreRepository(IDbContextProvider<StoreDbContext> dbContextProvider) : base(dbContextProvider)
{
}
}

3
be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/StoreDbContext.cs

@ -18,6 +18,7 @@ public class StoreDbContext : AbpDbContext<StoreDbContext>, IStoreDbContext
public DbSet<TransferRequest> TransferRequests { get; set; }
public DbSet<ProductReceiptRequest> ProductReceiptRequests { get; set; }
public DbSet<MaterialRequest> MaterialRequests { get; set; }
public DbSet<InjectionRequest> InjectionRequests { get; set; }
public DbSet<ContainerRequest> ContainerRequests { get; set; }
public DbSet<DeliverRequest> DeliverRequests { get; set; }
public DbSet<InspectRequest> InspectRequests { get; set; }
@ -69,6 +70,7 @@ public class StoreDbContext : AbpDbContext<StoreDbContext>, IStoreDbContext
public DbSet<InventoryTransferNote> InventoryTransferNotes { get; set; }
public DbSet<WarehouseTransferNote> WarehouseTransferNotes { get; set; }
public DbSet<IssueNote> IssueNotes { get; set; }
public DbSet<InjectionNote> InjectionNotes { get; set; }
public DbSet<ContainerNote> ContainerNotes { get; set; }
public DbSet<UnplannedReceiptNote> UnplannedReceiptNotes { get; set; }
public DbSet<UnplannedIssueNote> UnplannedIssueNotes { get; set; }
@ -94,6 +96,7 @@ public class StoreDbContext : AbpDbContext<StoreDbContext>, IStoreDbContext
public DbSet<InspectJob> InspectJobs { get; set; }
public DbSet<PutawayJob> PutawayJobs { get; set; }
public DbSet<IssueJob> IssueJobs { get; set; }
public DbSet<InjectionJob> InjectionJobs { get; set; }
public DbSet<ContainerJob> ContainerJobs { get; set; }
public DbSet<DeliverJob> DeliverJobs { get; set; }
public DbSet<JisDeliverJob> JisDeliverJobs { get; set; }

3
be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/StoreDbContextModelCreatingExtensions.cs

@ -54,6 +54,7 @@ public static class StoreDbContextModelCreatingExtensions
builder.ConfigureProductReceiptRequest(options);
builder.ConfigurePurchaseReceiptRequest(options);
builder.ConfigureMaterialRequest(options);
builder.ConfigureInjectionRequest(options);
builder.ConfigureDeliverRequest(options);
builder.ConfigureContainerRequest(options);
builder.ConfigureInspectRequest(options);
@ -87,6 +88,7 @@ public static class StoreDbContextModelCreatingExtensions
builder.ConfigureInventoryTransferNote(options);
builder.ConfigureWarehouseTransferNote(options);
builder.ConfigureIssueNote(options);
builder.ConfigureInjectionNote(options);
builder.ConfigureContainerNote(options);
builder.ConfigureUnplannedReceiptNote(options);
builder.ConfigureUnplannedIssueNote(options);
@ -113,6 +115,7 @@ public static class StoreDbContextModelCreatingExtensions
builder.ConfigureInspectJob(options);
builder.ConfigurePutawayJob(options);
builder.ConfigureIssueJob(options);
builder.ConfigureInjectionJob(options);
builder.ConfigureContainerJob(options);
builder.ConfigureDeliverJob(options);
builder.ConfigureJisDeliverJob(options);

9
be/Modules/Store/src/Win_in.Sfs.Wms.Store.EntityFrameworkCore/StoreEntityFrameworkCoreModule.cs

@ -54,6 +54,7 @@ public class StoreEntityFrameworkCoreModule : AbpModule
context.Services.AddTransient<IProductReceiptRequestRepository, ProductReceiptRequestEfCoreRepository>();
context.Services.AddTransient<IPurchaseReceiptRequestRepository, PurchaseReceiptRequestEfCoreRepository>();
context.Services.AddTransient<IMaterialRequestRepository, MaterialRequestEfCoreRepository>();
context.Services.AddTransient<IInjectionRequestRepository, InjectionRequestEfCoreRepository>();
context.Services.AddTransient<IDeliverRequestRepository, DeliverRequestEfCoreRepository>();
context.Services.AddTransient<IContainerRequestRepository, ContainerRequestEfCoreRepository>();
context.Services.AddTransient<IInspectRequestRepository, InspectRequestEfCoreRepository>();
@ -88,6 +89,7 @@ public class StoreEntityFrameworkCoreModule : AbpModule
context.Services.AddTransient<IInventoryTransferNoteRepository, InventoryTransferNoteEfCoreRepository>();
context.Services.AddTransient<IWarehouseTransferNoteRepository, WarehouseTransferNoteEfCoreRepository>();
context.Services.AddTransient<IIssueNoteRepository, IssueNoteEfCoreRepository>();
context.Services.AddTransient<IInjectionNoteRepository, InjectionNoteEfCoreRepository>();
context.Services.AddTransient<IContainerNoteRepository, ContainerNoteEfCoreRepository>();
context.Services.AddTransient<IUnplannedReceiptNoteRepository, UnplannedReceiptNoteEfCoreRepository>();
context.Services.AddTransient<IUnplannedIssueNoteRepository, UnplannedIssueNoteEfCoreRepository>();
@ -114,6 +116,7 @@ public class StoreEntityFrameworkCoreModule : AbpModule
context.Services.AddTransient<IInspectJobRepository, InspectJobEfCoreRepository>();
context.Services.AddTransient<IPutawayJobRepository, PutawayJobEfCoreRepository>();
context.Services.AddTransient<IIssueJobRepository, IssueJobEfCoreRepository>();
context.Services.AddTransient<IInjectionJobRepository, InjectionJobEfCoreRepository>();
context.Services.AddTransient<IContainerJobRepository, ContainerJobEfCoreRepository>();
context.Services.AddTransient<IDeliverJobRepository, DeliverJobEfCoreRepository>();
context.Services.AddTransient<IJisDeliverJobRepository, JisDeliverJobEfCoreRepository>();
@ -174,6 +177,8 @@ public class StoreEntityFrameworkCoreModule : AbpModule
orderOptions.DefaultWithDetailsFunc = query => query.Include(o => o.Details));
options.Entity<MaterialRequest>(orderOptions =>
orderOptions.DefaultWithDetailsFunc = query => query.Include(o => o.Details));
options.Entity<InjectionRequest>(orderOptions =>
orderOptions.DefaultWithDetailsFunc = query => query.Include(o => o.Details));
options.Entity<ContainerRequest>(orderOptions =>
orderOptions.DefaultWithDetailsFunc = query => query.Include(o => o.Details));
options.Entity<PurchaseReceiptRequest>(orderOptions =>
@ -222,6 +227,8 @@ public class StoreEntityFrameworkCoreModule : AbpModule
orderOptions.DefaultWithDetailsFunc = query => query.Include(o => o.Details));
options.Entity<IssueNote>(orderOptions =>
orderOptions.DefaultWithDetailsFunc = query => query.Include(o => o.Details));
options.Entity<InjectionNote>(orderOptions =>
orderOptions.DefaultWithDetailsFunc = query => query.Include(o => o.Details));
options.Entity<ContainerNote>(orderOptions =>
orderOptions.DefaultWithDetailsFunc = query => query.Include(o => o.Details));
options.Entity<ScrapNote>(orderOptions =>
@ -293,6 +300,8 @@ public class StoreEntityFrameworkCoreModule : AbpModule
orderOptions.DefaultWithDetailsFunc = query => query.Include(o => o.Details));
options.Entity<IssueJob>(orderOptions =>
orderOptions.DefaultWithDetailsFunc = query => query.Include(o => o.Details));
options.Entity<InjectionJob>(orderOptions =>
orderOptions.DefaultWithDetailsFunc = query => query.Include(o => o.Details));
options.Entity<ContainerJob>(orderOptions =>
orderOptions.DefaultWithDetailsFunc = query => query.Include(o => o.Details));
options.Entity<PutawayJob>(orderOptions =>

92
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/AutoMapperProfiles/Jobs/InjectionJobAutoMapperProfile.cs

@ -0,0 +1,92 @@
using System;
using AutoMapper;
using Volo.Abp.AutoMapper;
using Win_in.Sfs.Shared.Application;
using Win_in.Sfs.Wms.Inventory.Application.Contracts;
using Win_in.Sfs.Wms.Store.Application.Contracts;
using Win_in.Sfs.Wms.Store.Domain;
namespace Win_in.Sfs.Wms.Store.Event;
public partial class StoreEventAutoMapperProfile : Profile
{
private void InjectionJobAutoMapperProfile()
{
CreateMap<InjectionJob, InjectionNote>()
.ForMember(x => x.JobNumber, y => y.MapFrom(d => d.Number))
.ForMember(x => x.RequestNumber, y => y.MapFrom(d => d.InjectionRequestNumber))
.ForMember(x => x.ActiveDate, y => y.MapFrom(d => DateTime.Now))
.ForMember(x => x.Worker, y => y.MapFrom(d => d.CompleteUserName))
.Ignore(x => x.Confirmed)
.Ignore(x => x.Number)
.Ignore(x => x.ConfirmTime);
CreateMap<InjectionJobDetail, InjectionNoteDetail>()
.ForMember(x => x.FromPackingCode, y => y.MapFrom(d => d.HandledPackingCode))
.ForMember(x => x.ToPackingCode, y => y.MapFrom(d => d.HandledPackingCode))
.ForMember(x => x.SupplierBatch, y => y.MapFrom(d => d.HandledSupplierBatch))
.ForMember(x => x.ArriveDate, y => y.MapFrom(d => d.HandledArriveDate))
.ForMember(x => x.ProduceDate, y => y.MapFrom(d => d.HandledProduceDate))
.ForMember(x => x.ExpireDate, y => y.MapFrom(d => d.HandledExpireDate))
.ForMember(x => x.FromLot, y => y.MapFrom(d => d.HandledLot))
.ForMember(x => x.ToLot, y => y.MapFrom(d => d.HandledLot))
.ForMember(x => x.ToContainerCode, y => y.MapFrom(d => d.HandledContainerCode))
.ForMember(x => x.FromContainerCode, y => y.MapFrom(d => d.HandledContainerCode))
.ForMember(x => x.FromStatus, y => y.MapFrom(d => d.Status))
.ForMember(x => x.ToStatus, y => y.MapFrom(d => d.Status))
.ForMember(x => x.Qty, y => y.MapFrom(d => d.HandledQty))
.ForMember(x => x.IssueTime, y => y.MapFrom(d => DateTime.Now))
.ForMember(x => x.FromLocationCode, y => y.MapFrom(d => d.HandledFromLocationCode))
.ForMember(x => x.FromLocationArea, y => y.MapFrom(d => d.HandledFromLocationArea))
.ForMember(x => x.FromLocationGroup, y => y.MapFrom(d => d.HandledFromLocationGroup))
.ForMember(x => x.FromLocationErpCode, y => y.MapFrom(d => d.HandledFromLocationErpCode))
.ForMember(x => x.FromWarehouseCode, y => y.MapFrom(d => d.HandledFromWarehouseCode))
.ForMember(x => x.ToLocationCode, y => y.MapFrom(d => d.ToLocationCode))
.Ignore(x => x.ToLocationArea)
.Ignore(x => x.ToLocationGroup)
.Ignore(x => x.ToLocationErpCode)
;
CreateMap<InjectionJobDetail, ExpectInEditInput>()
.MapExpectInOutFrom()
.Ignore(x => x.Worker)
.Ignore(x => x.SerialNumber)
.Ignore(x => x.ExtraProperties)
;
CreateMap<InjectionJobDetail, ExpectOutEditInput>()
.MapExpectInOutFrom()
.Ignore(x => x.Worker)
.Ignore(x => x.SerialNumber)
.Ignore(x => x.ExtraProperties);
CreateMap<InjectionJob, InjectionNoteEditInput>()
.ForMember(x => x.RequestNumber, y => y.MapFrom(d => d.InjectionRequestNumber))
.Ignore(x => x.Confirmed)
.Ignore(x => x.JobNumber)
.Ignore(x => x.ActiveDate)
;
CreateMap<InjectionJobDetail, InjectionNoteDetailInput>()
.ForMember(x => x.Qty, y => y.MapFrom(d => d.HandledQty))
.ForMember(x => x.IssueTime, y => y.MapFrom(d => DateTime.Now))
.ForMember(x => x.FromPackingCode, y => y.MapFrom(d => d.HandledPackingCode))
.ForMember(x => x.ToPackingCode, y => y.MapFrom(d => d.HandledPackingCode))
.ForMember(x => x.FromContainerCode, y => y.MapFrom(d => d.HandledContainerCode))
.ForMember(x => x.ToContainerCode, y => y.MapFrom(d => d.HandledContainerCode))
.ForMember(x => x.FromLot, y => y.MapFrom(d => d.HandledLot))
.ForMember(x => x.ToLot, y => y.MapFrom(d => d.HandledLot))
.ForMember(x => x.SupplierBatch, y => y.MapFrom(d => d.HandledSupplierBatch))
.ForMember(x => x.ArriveDate, y => y.MapFrom(d => d.HandledArriveDate))
.ForMember(x => x.ProduceDate, y => y.MapFrom(d => d.HandledProduceDate))
.ForMember(x => x.ExpireDate, y => y.MapFrom(d => d.ExpiredTime))
.ForMember(x => x.FromLocationCode, y => y.MapFrom(d => d.HandledFromLocationCode))
.ForMember(x => x.FromLocationArea, y => y.MapFrom(d => d.HandledFromLocationArea))
.ForMember(x => x.FromLocationGroup, y => y.MapFrom(d => d.HandledFromLocationGroup))
.ForMember(x => x.FromLocationErpCode, y => y.MapFrom(d => d.HandledFromLocationErpCode))
.ForMember(x => x.FromWarehouseCode, y => y.MapFrom(d => d.HandledFromWarehouseCode))
.ForMember(x => x.FromStatus, y => y.MapFrom(d => d.Status))
.ForMember(x => x.ToStatus, y => y.MapFrom(d => d.Status))
;
}
}

134
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/AutoMapperProfiles/Requests/InjectionRequestAutoMapperProfile.cs

@ -0,0 +1,134 @@
using AutoMapper;
using Volo.Abp.AutoMapper;
using Win_in.Sfs.Shared.Application;
using Win_in.Sfs.Wms.Inventory.Application.Contracts;
using Win_in.Sfs.Wms.Store.Application.Contracts;
using Win_in.Sfs.Wms.Store.Domain;
namespace Win_in.Sfs.Wms.Store.Event;
public partial class StoreEventAutoMapperProfile : Profile
{
private void InjectionRequestAutoMapperProfile()
{
CreateMap<InjectionRequest, InjectionJobEditInput>()
.ForMember(x => x.InjectionRequestNumber, y => y.MapFrom(d => d.Number))
.ForMember(x => x.RequestType, y => y.MapFrom(d => d.Type))
.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)
;
CreateMap<InjectionRequestDetail, InjectionJobDetailInput>()
.ForMember(x => x.RequestLocationCode, y => y.MapFrom(d => d.ToLocationCode))
.Ignore(x => x.RecommendFromLocationArea)
.Ignore(x => x.RecommendFromLocationGroup)
.Ignore(x => x.HandledFromLocationArea)
.Ignore(x => x.HandledFromLocationGroup)
.Ignore(x => x.RecommendFromWarehouseCode)
.Ignore(x => x.HandledFromWarehouseCode)
.Ignore(x => x.OnTheWayLocationCode)
.Ignore(x => x.DistributionType)
.Ignore(x => x.RoundedQty)
.Ignore(x => x.Operation)
.Ignore(x => x.ExpiredTime)
.Ignore(x => x.TruncType)
.Ignore(x => x.PlanBeginTime)
.Ignore(x => x.PlannedSplitRule)
.Ignore(x => x.DeliveryQty)
.Ignore(x => x.Status)
.Ignore(x => x.RecommendContainerCode)
.Ignore(x => x.StdPackQty)
.Ignore(x => x.RecommendPackingCode)
.Ignore(x => x.HandledContainerCode)
.Ignore(x => x.HandledPackingCode)
.Ignore(x => x.RecommendSupplierBatch)
.Ignore(x => x.RecommendProduceDate)
.Ignore(x => x.RecommendArriveDate)
.Ignore(x => x.RecommendExpireDate)
.Ignore(x => x.HandledFromLocationCode)
.Ignore(x => x.HandledFromLocationErpCode)
.Ignore(x => x.HandledUom)
.Ignore(x => x.RecommendFromLocationErpCode)
.Ignore(x => x.HandledExpireDate)
.Ignore(x => x.HandledLot)
.Ignore(x => x.HandledArriveDate)
.Ignore(x => x.HandledProduceDate)
.Ignore(x => x.HandledQty)
.Ignore(x => x.RecommendQty)
.Ignore(x => x.Uom)
.Ignore(x => x.HandledSupplierBatch)
.Ignore(x => x.RecommendFromLocationCode)
.Ignore(x => x.RecommendLot)
.IgnoreIHasRecommendAndHandledFrom();
CreateMap<BalanceDTO, InjectionJobDetailInput>()
.ForMember(x => x.RecommendArriveDate, y => y.MapFrom(d => d.ArriveDate))
.ForMember(x => x.RecommendContainerCode, y => y.MapFrom(d => d.ContainerCode))
.ForMember(x => x.RecommendExpireDate, y => y.MapFrom(d => d.ExpireDate))
.ForMember(x => x.RecommendFromLocationCode, y => y.MapFrom(d => d.LocationCode))
.ForMember(x => x.RecommendFromLocationErpCode, y => y.MapFrom(d => d.LocationErpCode))
.ForMember(x => x.RecommendFromWarehouseCode, y => y.MapFrom(d => d.WarehouseCode))
.ForMember(x => x.RecommendFromLocationArea, y => y.MapFrom(d => d.LocationArea))
.ForMember(x => x.RecommendFromLocationGroup, y => y.MapFrom(d => d.LocationGroup))
.ForMember(x => x.RecommendLot, y => y.MapFrom(d => d.Lot))
.ForMember(x => x.RecommendPackingCode, y => y.MapFrom(d => d.PackingCode))
.ForMember(x => x.RecommendProduceDate, y => y.MapFrom(d => d.ProduceDate))
.ForMember(x => x.RecommendQty, y => y.MapFrom(d => d.Qty))
.ForMember(x => x.RecommendSupplierBatch, y => y.MapFrom(d => d.SupplierBatch))
.ForMember(x => x.Uom, y => y.MapFrom(d => d.Uom)).Ignore(x => x.HandledArriveDate)
.Ignore(x => x.HandledFromLocationArea)
.Ignore(x => x.HandledFromLocationGroup)
.Ignore(x => x.ToLocationErpCode)
.Ignore(x => x.ToWarehouseCode)
.Ignore(x => x.ToLocationArea)
.Ignore(x => x.ToLocationGroup)
.Ignore(x => x.HandledFromWarehouseCode)
.Ignore(x => x.RequestLocationCode)
.Ignore(x => x.ToLocationCode)
.Ignore(x => x.ProdLine)
.Ignore(x => x.WorkStation)
.Ignore(x => x.HandledContainerCode)
.Ignore(x => x.HandledExpireDate)
.Ignore(x => x.HandledFromLocationCode)
.Ignore(x => x.HandledFromLocationErpCode)
.Ignore(x => x.HandledLot)
.Ignore(x => x.HandledPackingCode)
.Ignore(x => x.HandledProduceDate)
.Ignore(x => x.HandledQty)
.Ignore(x => x.HandledSupplierBatch)
.Ignore(x => x.HandledUom)
.Ignore(x => x.Remark)
.Ignore(x => x.OnTheWayLocationCode)
.Ignore(x => x.DistributionType)
.Ignore(x => x.RoundedQty)
.Ignore(x => x.Operation)
.Ignore(x => x.ExpiredTime)
.Ignore(x => x.TruncType)
.Ignore(x => x.PlanBeginTime)
.Ignore(x => x.PlannedSplitRule)
.Ignore(x => x.DeliveryQty)
.Ignore(x => x.RequestLocationCode)
.Ignore(x => x.ToLocationCode)
.Ignore(x => x.ProdLine)
.Ignore(x => x.WorkStation)
.Ignore(x => x.PositionCode)
.Ignore(x => x.RecommendType)
.IgnoreIHasRecommendAndHandledFrom();
}
}

130
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/Jobs/InjectionJobEventHandler.cs

@ -0,0 +1,130 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.EventBus;
using Volo.Abp.Uow;
using Win_in.Sfs.Basedata.Application.Contracts;
using Win_in.Sfs.Shared.Domain.Shared;
using Win_in.Sfs.Shared.Event;
using Win_in.Sfs.Wms.Store.Application.Contracts;
using Win_in.Sfs.Wms.Store.Domain;
using Win_in.Sfs.Wms.Store.Domain.Shared;
namespace Win_in.Sfs.Wms.Store.Event.BusinessJob;
public class InjectionJobEventHandler :
StoreEventHandlerBase
, ILocalEventHandler<SfsCompletedEntityEventData<InjectionJob>>
{
private const EnumTransType TransType = EnumTransType.Issue;
private readonly IInjectionNoteAppService _injectionNoteAppService;
private readonly ILocationAppService _locationAppService;
public InjectionJobEventHandler(IInjectionNoteAppService injectionNoteAppService, ILocationAppService locationAppService)
{
_injectionNoteAppService = injectionNoteAppService;
_locationAppService = locationAppService;
}
/// <summary>
/// 执行后
/// </summary>
/// <param name="eventData"></param>
/// <returns></returns>
[UnitOfWork]
public virtual async Task HandleEventAsync(SfsCompletedEntityEventData<InjectionJob> eventData)
{
var entity = eventData.Entity;
var injectionNote = await BuildInjectionNoteAsync(entity).ConfigureAwait(false);
await _injectionNoteAppService.CreateAsync(injectionNote).ConfigureAwait(false);
}
#region 私有
/// <summary>
/// 创建补料记录实体
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
private async Task<InjectionNoteEditInput> BuildInjectionNoteAsync(InjectionJob entity)
{
var injectionNoteCreateInput = ObjectMapper.Map<InjectionJob, InjectionNoteEditInput>(entity);
injectionNoteCreateInput.JobNumber = entity.Number;
var locationCodes = injectionNoteCreateInput.Details.Select(p => p.ToLocationCode).Distinct().ToList();
var locations = await _locationAppService.GetByCodesAsync(locationCodes).ConfigureAwait(false);
injectionNoteCreateInput.Details.RemoveAll(p => p.Qty == 0);
foreach (var detail in injectionNoteCreateInput.Details)
{
var location = locations.First(p => p.Code == detail.ToLocationCode);
await RemovePackingCodeAndContainerCodeAndLotAsync(detail, location.Type).ConfigureAwait(false); //去箱 去托 去批
detail.ToLocationArea = location.AreaCode;
detail.ToLocationGroup = location.LocationGroupCode;
detail.ToLocationErpCode = location.ErpLocationCode;
detail.ToWarehouseCode = location.WarehouseCode;
}
return injectionNoteCreateInput;
}
/// <summary>
/// 去除箱码 托码 批次
/// </summary>
private async Task RemovePackingCodeAndContainerCodeAndLotAsync(InjectionNoteDetailInput injectionNoteDetail,
EnumLocationType locationType)
{
switch (locationType)
{
case EnumLocationType.WIP:
{
//用开关控制 发料到线边后去除箱码和托码 ???
if (await SettingManager.IsTrueAsync(StoreSettings.Issue.ToWip.IsRemovePackingCode)
.ConfigureAwait(false))
{
injectionNoteDetail.ToPackingCode = "";
}
if (await SettingManager.IsTrueAsync(StoreSettings.Issue.ToWip.IsRemoveContainerCode)
.ConfigureAwait(false))
{
injectionNoteDetail.ToContainerCode = "";
}
if (await SettingManager.IsTrueAsync(StoreSettings.Issue.ToWip.IsRemoveLot).ConfigureAwait(false))
{
injectionNoteDetail.ToLot = "";
}
break;
}
case EnumLocationType.SEMI:
{
//用开关控制 发料到后去除箱码和托码 ???
if (await SettingManager.IsTrueAsync(StoreSettings.Issue.ToSemi.IsRemovePackingCode)
.ConfigureAwait(false))
{
injectionNoteDetail.ToPackingCode = "";
}
if (await SettingManager.IsTrueAsync(StoreSettings.Issue.ToSemi.IsRemoveContainerCode)
.ConfigureAwait(false))
{
injectionNoteDetail.ToContainerCode = "";
}
if (await SettingManager.IsTrueAsync(StoreSettings.Issue.ToSemi.IsRemoveLot).ConfigureAwait(false))
{
injectionNoteDetail.ToLot = "";
}
break;
}
}
}
#endregion
}

275
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/Requests/InjectionRequestEventHandler.cs

@ -0,0 +1,275 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using FluentValidation.Validators;
using Volo.Abp;
using Volo.Abp.EventBus;
using Volo.Abp.SettingManagement;
using Win_in.Sfs.Basedata.Application.Contracts;
using Win_in.Sfs.Shared.Domain.Shared;
using Win_in.Sfs.Shared.Event;
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;
namespace Win_in.Sfs.Wms.Store.Event.BusinessRequest;
public class InjectionRequestEventHandler
: StoreEventHandlerBase
, ILocalEventHandler<SfsHandledEntityEventData<InjectionRequest>>
, ILocalEventHandler<SfsAbortedEntityEventData<InjectionRequest>>
, ILocalEventHandler<SfsCompletedEntityEventData<InjectionRequest>>
, ILocalEventHandler<SfsCreatedEntityEventData<InjectionRequest>>
, ILocalEventHandler<SfsCreatedEntityEventData<List<InjectionRequest>>>
{
private readonly IInjectionJobAppService _injectionJobAppService;
private readonly IProductionLineAppService _productionLineAppService;
private readonly IInjectionRequestManager _injectionRequestManager;
private readonly ILocationAppService _locationAppService;
private readonly IBalanceAppService _balanceAppService;
public InjectionRequestEventHandler(
IInjectionJobAppService injectionJobAppService
, IProductionLineAppService productionLineAppService
, IInjectionRequestManager injectionRequestManager
, ILocationAppService locationAppService
, IBalanceAppService balanceAppService)
{
_injectionJobAppService = injectionJobAppService;
_productionLineAppService = productionLineAppService;
_injectionRequestManager = injectionRequestManager;
_locationAppService = locationAppService;
_balanceAppService = balanceAppService;
}
/// <summary>
/// 创建后
/// </summary>
/// <param name="eventData">Event data</param>
public virtual async Task HandleEventAsync(SfsCreatedEntityEventData<InjectionRequest> eventData)
{
var entity = eventData.Entity;
//if (entity.AutoSubmit)
//{
// await _injectionRequestManager.SubmitAsync(entity).ConfigureAwait(false);
//}
}
/// <summary>
/// 批量创建后
/// </summary>
/// <param name="eventData">Event data</param>
public virtual async Task HandleEventAsync(SfsCreatedEntityEventData<List<InjectionRequest>> eventData)
{
var entitys = eventData.Entity;
foreach (var entity in entitys)
{
if (entity.AutoSubmit)
{
await _injectionRequestManager.SubmitAsync(entity).ConfigureAwait(false);
}
}
}
/// <summary>
/// 执行后
/// </summary>
/// <param name="eventData"></param>
/// <returns></returns>
public virtual async Task HandleEventAsync(SfsHandledEntityEventData<InjectionRequest> eventData)
{
var entity = eventData.Entity;
var injectionJobs = await BuildInjectionJobAsync(entity).ConfigureAwait(false);
if (injectionJobs.Any())
{
await _injectionJobAppService.CreateManyAsync(injectionJobs).ConfigureAwait(false);
}
}
/// <summary>
/// 驳回后
/// </summary>
/// <param name="eventData"></param>
/// <returns></returns>
public virtual async Task HandleEventAsync(SfsAbortedEntityEventData<InjectionRequest> eventData)
{
}
/// <summary>
/// 完成后
/// </summary>
/// <param name="eventData"></param>
/// <returns></returns>
public virtual async Task HandleEventAsync(SfsCompletedEntityEventData<InjectionRequest> eventData)
{
_ = eventData.Entity;
// await _injectionJobAppService.CompleteByInjectionRequestAsync(entity.Number);
await Task.CompletedTask.ConfigureAwait(false);
}
#region 私有
private async Task<List<InjectionJobEditInput>> BuildInjectionJobAsync
(InjectionRequest injectionRequest)
{
var jobs = new List<InjectionJobEditInput>();
var transactionType = await TransactionTypeAclService.GetByTransTypeAsync(EnumTransType.Issue, EnumTransSubType.None).ConfigureAwait(false);//库存事务
var toLocationCodes = injectionRequest.Details.Select(p => p.ToLocationCode).Distinct().ToList();//所有发送库位的集合
var toLocations = await _locationAppService.GetByCodesAsync(toLocationCodes).ConfigureAwait(false);//所有库位的集合
var injectionRequestDetails = injectionRequest.Details.Where(p => p.ToBeIssuedQty > 0);//所有还没发送物品的集合
foreach (var injectionRequestDetail in injectionRequestDetails)//如果有还有剩余未叫料的数量 则创建新的任务
{
var toLocation = toLocations.FirstOrDefault(p => p.Code == injectionRequestDetail.ToLocationCode);//判断目标库位是否存在
Check.NotNull(toLocation, "库位代码", $"库位 {injectionRequestDetail.ToLocationCode} 不存在");
//创建详情
var jobDetails = await BuildInjectionJobDetailInputsAsync(injectionRequest, injectionRequestDetail, transactionType, toLocation.LocationGroupCode).ConfigureAwait(false);
if (!jobDetails.Any())
{
continue;
}
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.ToLocationCode != injectionRequestDetail.ToLocationCode))
{
job = BuildInjectionJobCreateInput(injectionRequest, fromLocation);
jobs.Add(job);
}
job.Details.AddRange(jobDetails);
if (injectionRequestDetail.ToBeIssuedQty < 0)
{
injectionRequestDetail.Status = EnumStatus.Close;
}
}
jobs = jobs.Where(p => p.Details.Any()).ToList();
var openRequestDetails =
injectionRequest.Details.Where(p => p.Status != EnumStatus.Close).ToList();
if (!openRequestDetails.Any())
{
return jobs;
}
var enableMultipleCreateInjectionJob = await SettingManager.IsTrueAsync(StoreSettings.InjectionRequest.EnableMultipleCreateInjectionJob).ConfigureAwait(false);
if (enableMultipleCreateInjectionJob)
{
injectionRequest.Partial();
}
else
{
var sb = new StringBuilder();
foreach (var openRequestDetail in openRequestDetails)
{
sb.AppendLine($"{openRequestDetail.ItemCode}请求数量 {openRequestDetail.Qty},可用库存数量 {openRequestDetail.IssuedQty}");
}
throw new UserFriendlyException($"{sb} 可用库存数量不足, 无法生成发料任务");
}
return jobs;
}
private InjectionJobEditInput BuildInjectionJobCreateInput(InjectionRequest injectionRequest, LocationDTO fromLocation)
{
InjectionJobEditInput job;
job = ObjectMapper.Map<InjectionRequest, InjectionJobEditInput>(injectionRequest);
job.JobType = EnumJobType.IssueJob;
job.JobStatus = EnumJobStatus.Open;
job.WorkGroupCode = fromLocation.WorkGroupCode;
job.WarehouseCode = fromLocation.WarehouseCode;
job.ProdLine = fromLocation.LocationGroupCode;
job.Worker = injectionRequest.Worker;
job.InjectionRequestNumber = injectionRequest.Number;
return job;
}
private async Task<List<InjectionJobDetailInput>> BuildInjectionJobDetailInputsAsync(InjectionRequest injectionRequest,
InjectionRequestDetail injectionRequestDetail, TransactionTypeDTO transactionType, string toLocationGroupCode)
{
var jobDetails = new List<InjectionJobDetailInput>();
var input = new RecommendBalanceRequestInput()
{
ItemCode = injectionRequestDetail.ItemCode,
Qty = injectionRequestDetail.ToBeIssuedQty,
LocationTypes = transactionType.OutLocationTypes,
LocationAreas = new List<string> { injectionRequestDetail.FromLocationArea },
Statuses = transactionType.OutInventoryStatuses,
};
//获取推荐库存
var recommendList = await _balanceAppService.GetRecommendBalancesAsync(input).ConfigureAwait(false);
//没有推荐库存时 跳过此明细 不生成任务
if (recommendList.Count != 0)
{
foreach (var recommend in recommendList)
{
//拿走需求量
var detail = await BuildInjectionJobDetailAsync(injectionRequestDetail, recommend, toLocationGroupCode).ConfigureAwait(false);
if (injectionRequest.UseOnTheWayLocation)
{
//获取在途库
var locationDto = await _locationAppService.GetFirstByTypeAsync(EnumLocationType.TRANSPORT).ConfigureAwait(false);
detail.OnTheWayLocationCode = locationDto.Code;
}
jobDetails.Add(detail);
injectionRequestDetail.IssuedQty += recommend.Qty;
await _injectionRequestManager.UpdateDetailsAsync(injectionRequest).ConfigureAwait(false);
}
}
return jobDetails;
}
private async Task<InjectionJobDetailInput> BuildInjectionJobDetailAsync(InjectionRequestDetail injectionRequestDetail, BalanceDTO balance, string toLocationGroupCode)
{
ProductionLineDTO prodLine = await _productionLineAppService.GetByLocationGroupCodeAsync(toLocationGroupCode).ConfigureAwait(false);
var detail = ObjectMapper.Map<BalanceDTO, InjectionJobDetailInput>(balance);
detail.RequestLocationCode = injectionRequestDetail.ToLocationCode;
detail.WorkStation = injectionRequestDetail.WorkStation;
detail.ExpiredTime = injectionRequestDetail.ExpiredTime;
detail.PositionCode = injectionRequestDetail.PositionCode;
detail.RecommendType = injectionRequestDetail.RecommendType;
detail.RecommendPackingCode = balance.PackingCode;
detail.RecommendContainerCode = balance.ContainerCode;
detail.RecommendSupplierBatch = balance.SupplierBatch;
detail.RecommendProduceDate = balance.ProduceDate;
detail.RecommendExpireDate = balance.ExpireDate;
detail.RecommendLot = balance.Lot;
detail.RecommendProduceDate = balance.ProduceDate;
detail.RecommendArriveDate = balance.ArriveDate;
detail.RecommendFromLocationArea = balance.LocationArea;
detail.RecommendFromLocationCode = balance.LocationCode;
detail.RecommendFromLocationErpCode = balance.LocationErpCode;
detail.RecommendFromLocationGroup = balance.LocationGroup;
detail.RecommendFromWarehouseCode = balance.WarehouseCode;
detail.RecommendQty = balance.Qty;
detail.Uom = balance.Uom;
detail.ToLocationCode = injectionRequestDetail.ToLocationCode;
detail.ToLocationErpCode = injectionRequestDetail.ToLocationErpCode;
detail.ToLocationArea = injectionRequestDetail.ToLocationArea;
detail.ToWarehouseCode = injectionRequestDetail.ToWarehouseCode;
detail.ToLocationGroup = injectionRequestDetail.ToLocationGroup;
detail.ProdLine = prodLine == null ? toLocationGroupCode : prodLine.Code;
await Task.CompletedTask.ConfigureAwait(false);
return detail;
}
#endregion
}

2
be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/StoreEventAutoMapperProfile.cs

@ -35,6 +35,7 @@ public partial class StoreEventAutoMapperProfile : Profile
DeliverJobAutoMapperProfile();
InspectJobAutoMapperProfile();
IssueJobAutoMapperProfile();
InjectionJobAutoMapperProfile();
JisDeliverJobAutoMapperProfile();
ProductionReturnJobAutoMapperProfile();
ProductReceiveJobAutoMapperProfile();
@ -69,6 +70,7 @@ public partial class StoreEventAutoMapperProfile : Profile
JisDeliverNoteAutoMapperProfile();
JisProductReceiptNoteAutoMapperProfile();
MaterialRequestAutoMapperProfile();
InjectionRequestAutoMapperProfile();
ProductionReturnRequestAutoMapperProfile();
ProductionReturnNoteAutoMapperProfile();
ProductReceiptNoteAutoMapperProfile();

Loading…
Cancel
Save