62 changed files with 3691 additions and 1 deletions
@ -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; } |
|||
|
|||
} |
@ -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; } |
|||
} |
@ -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); |
|||
|
|||
} |
@ -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))); |
|||
|
|||
} |
|||
} |
@ -0,0 +1,6 @@ |
|||
namespace Win_in.Sfs.Wms.Store.Application.Contracts; |
|||
|
|||
public class InjectionJobCheckInput : SfsJobCheckInputBase |
|||
{ |
|||
|
|||
} |
@ -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; } |
|||
} |
@ -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
|
|||
} |
@ -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; } |
|||
|
|||
} |
@ -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; } |
|||
|
|||
} |
@ -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); |
|||
} |
@ -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))); |
|||
} |
|||
} |
@ -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; } |
|||
|
|||
} |
@ -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
|
|||
} |
@ -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; } |
|||
} |
@ -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; } |
|||
|
|||
} |
@ -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; |
|||
|
|||
} |
@ -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); |
|||
|
|||
} |
@ -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))); |
|||
|
|||
} |
|||
} |
@ -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; } |
|||
|
|||
|
|||
} |
@ -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
|
|||
} |
@ -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; } |
|||
} |
@ -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; |
|||
} |
|||
} |
@ -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); |
|||
|
|||
} |
|||
} |
@ -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; |
|||
} |
|||
|
|||
} |
@ -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); |
|||
; |
|||
} |
|||
} |
@ -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; |
|||
} |
|||
} |
@ -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); |
|||
} |
|||
} |
@ -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); |
|||
} |
@ -0,0 +1,6 @@ |
|||
namespace Win_in.Sfs.Wms.Store.Domain; |
|||
|
|||
public interface IIssueJobRepository : ISfsJobRepositoryBase<IssueJob> |
|||
{ |
|||
|
|||
} |
@ -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); |
|||
} |
|||
|
|||
} |
@ -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; |
|||
} |
|||
} |
@ -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); |
|||
} |
|||
} |
@ -1,6 +1,6 @@ |
|||
namespace Win_in.Sfs.Wms.Store.Domain; |
|||
|
|||
public interface IIssueJobRepository : ISfsJobRepositoryBase<IssueJob> |
|||
public interface IInjectionJobRepository : ISfsJobRepositoryBase<InjectionJob> |
|||
{ |
|||
|
|||
} |
|||
|
@ -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); |
|||
|
|||
} |
@ -0,0 +1,6 @@ |
|||
namespace Win_in.Sfs.Wms.Store.Domain; |
|||
|
|||
public interface IInjectionNoteRepository : ISfsStoreRepositoryBase<InjectionNote> |
|||
{ |
|||
|
|||
} |
@ -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($"当前状态为 【已确认】 ,无法再次确认!"); |
|||
} |
|||
|
|||
} |
|||
|
|||
} |
@ -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; } |
|||
} |
@ -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; |
|||
} |
|||
} |
|||
|
|||
} |
@ -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); |
|||
} |
@ -0,0 +1,9 @@ |
|||
using Win_in.Sfs.Shared.Domain; |
|||
|
|||
namespace Win_in.Sfs.Wms.Store.Domain; |
|||
|
|||
public interface IInjectionRequestRepository : ISfsStoreRepositoryBase<InjectionRequest>, |
|||
ISfsBulkRepositoryBase<InjectionRequest> |
|||
{ |
|||
|
|||
} |
@ -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>(); |
|||
} |
@ -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; } |
|||
} |
@ -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
|
|||
|
|||
} |
@ -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();
|
|||
}); |
|||
} |
|||
} |
@ -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) |
|||
{ |
|||
} |
|||
} |
@ -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 }); |
|||
}); |
|||
} |
|||
} |
@ -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) |
|||
{ |
|||
} |
|||
} |
@ -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 }); |
|||
}); |
|||
} |
|||
} |
@ -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) |
|||
{ |
|||
} |
|||
} |
@ -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)) |
|||
; |
|||
} |
|||
} |
@ -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(); |
|||
|
|||
} |
|||
} |
@ -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
|
|||
} |
@ -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
|
|||
} |
Loading…
Reference in new issue