Browse Source

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

dev_DY_CC
郑勃旭 12 months ago
parent
commit
dd948fdac7
  1. 187
      be/Hosts/WmsPda.Host/Win_in.Sfs.Wms.Pda.Host/Controllers/Jobs/IssueJobs/AssembleIssueJobsController.cs
  2. 135
      be/Hosts/WmsPda.Host/Win_in.Sfs.Wms.Pda.Host/Controllers/Stores/IssueRequest/AssembleRequestController.cs
  3. 8
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/AssembleIssueJobs/AssembleIssueJobPermissions.cs
  4. 2
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/AssembleIssueJobs/DTOs/AssembleIssueJobDTO.cs
  5. 10
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/AssembleIssueJobs/IAssembleIssueJobAppService.cs
  6. 3
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Jobs/IssueJobs/AssembleIssueJobs/Inputs/AssembleIssueJobEditInput.cs
  7. 15
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/AssembleIssueNotes/AssembleIssueNotePermissions.cs
  8. 1
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/AssembleIssueNotes/DTOs/AssembleIssueNoteDTO.cs
  9. 1
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/AssembleIssueNotes/IAssembleIssueNoteAppService.cs
  10. 2
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/AssembleIssueNotes/Inputs/AssembleIssueNoteEditInput.cs
  11. 2
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/AssembleIssueNotes/Inputs/AssembleIssueNoteImportInput.cs
  12. 8
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Notes/IssueNotes/KittingIssueNotes/KittingIssueNotePermissions.cs
  13. 10
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/IssueRequest/AssembleIssueRequests/AssembleIssueRequestPermissions.cs
  14. 4
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/IssueRequest/AssembleIssueRequests/DTOs/AssembleIssueRequestDTO.cs
  15. 59
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/IssueRequest/AssembleIssueRequests/DTOs/AssembleIssueRequestDetailDTO.cs
  16. 2
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/IssueRequest/AssembleIssueRequests/IAssembleIssueRequestAppService.cs
  17. 5
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/IssueRequest/AssembleIssueRequests/Inputs/AssembleIssueRequestEditInput.cs
  18. 10
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application.Contracts/Requests/IssueRequest/AssembleIssueRequests/Inputs/AssembleIssueRequestImportInput.cs
  19. 477
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Jobs/IssueJobs/AssembleIssueJobs/AssembleIssueJobAppService.cs
  20. 21
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Notes/IssueNotes/AssembleIssueNotes/AssembleIssueNoteAppService.cs
  21. 250
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Application/Requests/IssuelRequests/AssembleIssueRequests/AssembleIssueRequestAppService.cs
  22. 3
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/IssueJobs/AssembleIssueJobs/AssembleIssueJob.cs
  23. 2
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/IssueJobs/AssembleIssueJobs/AssembleIssueJobDetail.cs
  24. 5
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Jobs/IssueJobs/AssembleIssueJobs/AssembleIssueJobManager.cs
  25. 8
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Notes/IssueNotes/AssembleIssueNotes/AssembleIssueNote.cs
  26. 5
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/IssueRequests/AssembleIssueRequests/AssembleIssueRequest.cs
  27. 2
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/IssueRequests/AssembleIssueRequests/AssembleIssueRequestDetail.cs
  28. 32
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Domain/Requests/IssueRequests/AssembleIssueRequests/AssembleIssueRequestManager.cs
  29. 9
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/AutoMapperProfiles/Jobs/AssembleJobAutoMapperProfile.cs
  30. 1
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/AutoMapperProfiles/Notes/AssembleNoteAutoMapperProfile.cs
  31. 1
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/AutoMapperProfiles/Requests/AssembleIssueRequestAutoMapperProfile.cs
  32. 48
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/Jobs/AssembleIssueJobEventHandler.cs
  33. 664
      be/Modules/Store/src/Win_in.Sfs.Wms.Store.Event/Requests/AssembleIssueRequestEventHandler.cs

187
be/Hosts/WmsPda.Host/Win_in.Sfs.Wms.Pda.Host/Controllers/Jobs/IssueJobs/AssembleIssueJobsController.cs

@ -0,0 +1,187 @@
using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.AspNetCore.Mvc;
using Win_in.Sfs.Auth.Application.Contracts;
using Win_in.Sfs.Shared.Domain;
using Win_in.Sfs.Shared.Domain.Shared;
using Win_in.Sfs.Wms.Store.Application.Contracts;
namespace Win_in.Sfs.Wms.Pda.Controllers.Jobs.IssueJobs;
/// <summary>
/// </summary>
[ApiController]
[Route($"{PdaHostConst.ROOT_ROUTE}job/assemble-issue")]
public class AssembleIssueJobsController : AbpController
{
private readonly IAssembleIssueJobAppService _assembleIssueJobAppService;
private readonly IUserWorkGroupAppService _userWorkGroupAppService;
public AssembleIssueJobsController(IAssembleIssueJobAppService assembleIssueJobAppService, IUserWorkGroupAppService userWorkGroupAppService)
{
_assembleIssueJobAppService = assembleIssueJobAppService;
_userWorkGroupAppService = userWorkGroupAppService;
}
/// <summary>
/// 获取列表
/// </summary>
/// <param name="pageSize"></param>
/// <param name="pageIndex"></param>
/// <param name="isFinished"></param>
/// <returns></returns>
[HttpPost("list")]
public virtual async Task<PagedResultDto<AssembleIssueJobDTO>> GetListAsync(int pageSize, int pageIndex,
bool isFinished)
{
var status = new List<int>();
if (isFinished)
{
status.Add((int)EnumJobStatus.Done);
}
else
{
status.Add((int)EnumJobStatus.Open);
status.Add((int)EnumJobStatus.Wait);
status.Add((int)EnumJobStatus.Doing);
status.Add((int)EnumJobStatus.Partial);
}
var jsonStatus = JsonSerializer.Serialize(status);
var request = new SfsJobRequestInputBase
{
MaxResultCount = pageSize,
SkipCount = (pageIndex - 1) * pageSize,
Sorting = $"{nameof(ContainerJobDTO.CreationTime)} ASC",
Condition = new Condition
{
Filters = new List<Filter> { new(nameof(ContainerJobDTO.JobStatus), jsonStatus, "In") }
}
};
var list = await _assembleIssueJobAppService.GetPagedListByFilterAsync(request, true).ConfigureAwait(false);
return list;
}
/// <summary>
/// 承接任务
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
[HttpPost("take/{id}")]
public virtual async Task TakeAsync(Guid id)
{
await _assembleIssueJobAppService.AcceptAsync(id).ConfigureAwait(false);
}
/// <summary>
/// 取消承接任务
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
[HttpPost("cancel-take/{id}")]
public virtual async Task CancelTakeAsync(Guid id)
{
await _assembleIssueJobAppService.CancelAcceptAsync(id).ConfigureAwait(false);
}
/// <summary>
/// 执行任务明细
/// </summary>
/// <returns></returns>
[HttpPost("ExecuteDetail/{masterId}")]
public async Task ExecuteDetailAsync(Guid masterId, Guid detailId, AssembleIssueJobDetailDTO issueJobDetailDto)
{
await _assembleIssueJobAppService.ExecuteDetailAsync(masterId, detailId, issueJobDetailDto).ConfigureAwait(false);
}
/// <summary>
/// 获取任务数量
/// </summary>
/// <returns></returns>
[HttpGet("count")]
public virtual async Task<ActionResult<long>> CountAsync()
{
var status = new List<int>
{
(int)EnumJobStatus.Open, (int)EnumJobStatus.Doing, (int)EnumJobStatus.Partial, (int)EnumJobStatus.Wait
};
var jsonStatus = JsonSerializer.Serialize(status);
var request = new SfsJobRequestInputBase
{
Sorting = $"{nameof(InspectJobDTO.Priority)} ASC",
Condition = new Condition
{
Filters = new List<Filter>
{
//new(nameof(InspectJobDTO.WorkGroupCode),jsonCodes,"In"),
new(nameof(InspectJobDTO.JobStatus), jsonStatus, "In")
}
}
};
var count = await _assembleIssueJobAppService.GetCountByFilterAsync(request).ConfigureAwait(false);
return Ok(count);
}
/// <summary>
/// 获取任务详情
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
[HttpGet("{id}")]
public virtual async Task<ActionResult<AssembleIssueJobDTO>> GetAsync(Guid id)
{
var result = await _assembleIssueJobAppService.GetAsync(id).ConfigureAwait(false);
return Ok(result);
}
/// <summary>
/// 根据Job Number 获取盘点任务列表
/// </summary>
/// <param name="jobNumber"></param>
/// <returns></returns>
[HttpGet("by-number/{jobNumber}")]
public virtual async Task<ActionResult<AssembleIssueJobDTO>> GetByNumberAsync(string jobNumber)
{
var jobDto = await _assembleIssueJobAppService.GetByNumberAsync(jobNumber).ConfigureAwait(false);
if (jobDto == null)
{
throw new UserFriendlyException($"未找到编号为 {jobNumber} 的任务");
}
var wlgCodes = await _userWorkGroupAppService.GetCodsOfCurrentUserAsync().ConfigureAwait(false);
if (!wlgCodes.Contains(jobDto.WorkGroupCode))
{
return new NotFoundObjectResult($"任务属于工作组 {jobDto.WorkGroupCode}");
}
if (jobDto.JobStatus == EnumJobStatus.Doing && jobDto.AcceptUserId != CurrentUser.Id)
{
return new NotFoundObjectResult($"任务正在被 {jobDto.AcceptUserName} 处理");
}
return jobDto;
}
/// <summary>
///
/// </summary>
/// <param name="requestNumber"></param>
/// <returns></returns>
[HttpPost("by-request-number/{requestNumber}")]
public virtual async Task<List<AssembleIssueJobDTO>> GetByRequestNumberAsync(string requestNumber)
{
return await _assembleIssueJobAppService.GetByRequestNumberAsync(requestNumber).ConfigureAwait(false);
}
}

135
be/Hosts/WmsPda.Host/Win_in.Sfs.Wms.Pda.Host/Controllers/Stores/IssueRequest/AssembleRequestController.cs

@ -0,0 +1,135 @@
using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.AspNetCore.Mvc;
using Win_in.Sfs.Auth.Application.Contracts;
using Win_in.Sfs.Shared.Domain;
using Win_in.Sfs.Shared.Domain.Shared;
using Win_in.Sfs.Wms.Store.Application.Contracts;
namespace Win_in.Sfs.Wms.Pda.Controllers.Stores;
/// <summary>
/// 装配叫料请求
/// </summary>
[ApiController]
[Route($"{PdaHostConst.ROOT_ROUTE}store/assemble-request")]
public class AssembleRequestController : AbpController
{
private readonly IAssembleIssueRequestAppService _assembleIssueRequestAppService;
private readonly IUserWorkGroupAppService _userWorkGroupAppService;
/// <summary>
/// </summary>
/// <param name="assembleIssueRequestAppService"></param>
public AssembleRequestController(IAssembleIssueRequestAppService assembleIssueRequestAppService,
IUserWorkGroupAppService userWorkGroupAppService)
{
_assembleIssueRequestAppService = assembleIssueRequestAppService;
_userWorkGroupAppService = userWorkGroupAppService;
}
/// <summary>
/// Kitting叫料申请
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[HttpPost("")]
public virtual async Task CreateAsync(AssembleIssueRequestEditInput input)
{
await _assembleIssueRequestAppService.CreateAndHandleAsync(input).ConfigureAwait(false);
}
/// <summary>
/// </summary>
/// <param name="pageSize"></param>
/// <param name="pageIndex"></param>
/// <param name="isFinished"></param>
/// <returns></returns>
[HttpPost("list")]
public virtual async Task<PagedResultDto<AssembleIssueRequestDTO>> GetListAsync(int pageSize, int pageIndex,
bool isFinished)
{
var status = new List<int>();
if (isFinished)
{
status.Add((int)EnumRequestStatus.Completed);
}
else
{
status.Add((int)EnumRequestStatus.Partial);
status.Add((int)EnumRequestStatus.Handling);
status.Add((int)EnumRequestStatus.New);
}
var jsonStatus = JsonSerializer.Serialize(status);
var request = new SfsStoreRequestInputBase
{
MaxResultCount = pageSize,
SkipCount = (pageIndex - 1) * pageSize,
Sorting = $"{nameof(AssembleIssueRequestDTO.CreationTime)} ASC",
Condition = new Condition
{
Filters = new List<Filter> { new(nameof(AssembleIssueRequestDTO.RequestStatus), jsonStatus, "In") }
}
};
var list = await _assembleIssueRequestAppService.GetPagedListByFilterAsync(request, true).ConfigureAwait(false);
return list;
}
/// <summary>
/// </summary>
/// <param name="id"></param>
[HttpPost("handle/{id}")]
public virtual async Task HandleAsync(Guid id)
{
await _assembleIssueRequestAppService.HandleAsync(id).ConfigureAwait(false);
}
/// <summary>
/// 根据Job Number 获取盘点任务列表
/// </summary>
/// <param name="requestNumber"></param>
/// <returns></returns>
[HttpGet("by-number/{requestNumber}")]
public virtual async Task<ActionResult<AssembleIssueRequestDTO>> GetByNumberAsync(string requestNumber)
{
var jobDto = await _assembleIssueRequestAppService.GetByNumberAsync(requestNumber).ConfigureAwait(false);
if (jobDto == null)
{
throw new UserFriendlyException($"未找到编号为 {requestNumber} 的请求");
}
return jobDto;
}
/// <summary>
/// 获取任务详情
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
[HttpGet("{id}")]
public virtual async Task<ActionResult<AssembleIssueRequestDTO>> GetAsync(Guid id)
{
var result = await _assembleIssueRequestAppService.GetAsync(id).ConfigureAwait(false);
return Ok(result);
}
/// <summary>
///
/// </summary>
/// <returns></returns>
[HttpPost("IsHasNewJob")]
public virtual async Task<string> IsHasNewJobAsync(string requestNumber, List<string> jobNumber)
{
return await _assembleIssueRequestAppService.IsHasNewJobAsync(requestNumber, jobNumber).ConfigureAwait(false);
}
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

@ -52,5 +52,7 @@ public class AssembleIssueNoteEditInput : SfsStoreCreateOrUpdateInputBase
/// </summary> /// </summary>
[Display(Name = "使用在途库")] [Display(Name = "使用在途库")]
public bool UseOnTheWayLocation { get; set; } public bool UseOnTheWayLocation { get; set; }
public EnumIssueSendType EnumIssueSendType { get; set; }
#endregion #endregion
} }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

@ -21,9 +21,4 @@ public class AssembleIssueRequest : SfsStoreRequestAggregateRootBase<AssembleIss
/// </summary> /// </summary>
public bool UseOnTheWayLocation { get; set; } public bool UseOnTheWayLocation { get; set; }
/// <summary>
/// 明细列表
/// </summary>
[IgnoreUpdate]
public override List<AssembleIssueRequestDetail> Details { get; set; } = new List<AssembleIssueRequestDetail>();
} }

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

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

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

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

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

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

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

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

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

@ -30,6 +30,7 @@ public partial class StoreEventAutoMapperProfile : Profile
.Ignore(x => x.CompleteUserName) .Ignore(x => x.CompleteUserName)
.Ignore(x => x.CompleteTime) .Ignore(x => x.CompleteTime)
.Ignore(x => x.Details) .Ignore(x => x.Details)
.Ignore(x => x.EnumIssueSendType)
; ;
} }

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

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

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

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

Loading…
Cancel
Save