|
|
@ -1,14 +1,21 @@ |
|
|
|
using System; |
|
|
|
using System.Collections.Generic; |
|
|
|
using System.ComponentModel.DataAnnotations; |
|
|
|
using System.Linq; |
|
|
|
using System.Text; |
|
|
|
using System.Threading.Tasks; |
|
|
|
using Microsoft.AspNetCore.Authorization; |
|
|
|
using Microsoft.AspNetCore.Mvc; |
|
|
|
using Microsoft.EntityFrameworkCore; |
|
|
|
using Microsoft.Extensions.Logging; |
|
|
|
using Volo.Abp; |
|
|
|
using Volo.Abp.Domain.Repositories; |
|
|
|
using Volo.Abp.Validation; |
|
|
|
using Win_in.Sfs.Basedata.Application.Contracts; |
|
|
|
using Win_in.Sfs.Shared.Application.Contracts; |
|
|
|
using Win_in.Sfs.Shared.Domain; |
|
|
|
using Win_in.Sfs.Shared.Domain.Shared; |
|
|
|
using Win_in.Sfs.Wms.Inventory.Application.Contracts; |
|
|
|
using Win_in.Sfs.Wms.Store.Application.Contracts; |
|
|
|
using Win_in.Sfs.Wms.Store.Domain; |
|
|
|
using Win_in.Sfs.Wms.Store.Domain.Shared; |
|
|
@ -26,17 +33,206 @@ public class CountJobAppService |
|
|
|
ICountJobAppService |
|
|
|
{ |
|
|
|
private readonly ICountJobManager _countJobManager; |
|
|
|
|
|
|
|
private readonly IItemBasicAppService _itemBasicAppService; |
|
|
|
private readonly IItemStoreRelationAppService _itemStoreRelationAppService; |
|
|
|
private readonly IBalanceAppService _balanceAppService; |
|
|
|
//private readonly ILocationCapacityAppService _locationCapacityAppService;
|
|
|
|
|
|
|
|
public CountJobAppService( |
|
|
|
ICountJobRepository repository |
|
|
|
, ICountJobManager countJobManager |
|
|
|
, IItemBasicAppService itemBasicAppService |
|
|
|
, IItemStoreRelationAppService itemStoreRelationAppService |
|
|
|
, IBalanceAppService balanceAppService |
|
|
|
) : base(repository, countJobManager) |
|
|
|
{ |
|
|
|
_itemBasicAppService = itemBasicAppService; |
|
|
|
_countJobManager = countJobManager; |
|
|
|
_itemStoreRelationAppService = itemStoreRelationAppService; |
|
|
|
_balanceAppService= balanceAppService; |
|
|
|
} |
|
|
|
#region 导入
|
|
|
|
/// <summary>
|
|
|
|
/// 导入数据具体实现,可重写
|
|
|
|
/// </summary>
|
|
|
|
protected override async Task<SfsImportResult> ImportInternalAsync(SfsImportRequestInput requestInput, byte[] inputFileBytes) |
|
|
|
{ |
|
|
|
IList<CountJobImportInput> modelList = null; |
|
|
|
var modelDict = new Dictionary<CountJobImportInput, List<ValidationResult>>(); |
|
|
|
var entityDict = new Dictionary<CountJob, EntityState>(); |
|
|
|
try |
|
|
|
{ |
|
|
|
var hasDetails = typeof(CountJob).GetInterfaces().Any(o => o.IsGenericType && o.GetGenericTypeDefinition() == typeof(IMasterEntity<>)); |
|
|
|
modelDict = ExportImportService.ImportHaveValidationResult<CountJobImportInput>(inputFileBytes); |
|
|
|
foreach (var modelDictItem in modelDict) |
|
|
|
{ |
|
|
|
// DataAnnotations 静态验证
|
|
|
|
var validationRresults = modelDictItem.Value; |
|
|
|
var model = modelDictItem.Key; |
|
|
|
Validator.TryValidateObject(model, new ValidationContext(model, null, null), validationRresults); |
|
|
|
} |
|
|
|
modelList = modelDict.Keys.ToList(); |
|
|
|
List<CountJobDependentDetail> depDetails = new List<CountJobDependentDetail>(); |
|
|
|
// 如果没有验证错误或允许部分导入
|
|
|
|
var jobnumber = modelDict.First().Key.CountJobNumber; |
|
|
|
var job = await _repository.FindAsync(r => r.Number == jobnumber).ConfigureAwait(false); |
|
|
|
if (!modelDict.SelectMany(o => o.Value).Any() || requestInput.IsAllowPartImport) |
|
|
|
{ |
|
|
|
|
|
|
|
foreach (var item in modelDict) |
|
|
|
{ |
|
|
|
var model = item.Key; |
|
|
|
var validationRresults = item.Value; |
|
|
|
var depDetail = ObjectMapper.Map<CountJobImportInput, CountJobDependentDetail>(model); |
|
|
|
await ValidateImportModelAsync(model, validationRresults, job, depDetail).ConfigureAwait(false); |
|
|
|
depDetails.Add(depDetail); |
|
|
|
} |
|
|
|
} |
|
|
|
if (!modelDict.SelectMany(o => o.Value).Any()) |
|
|
|
{ |
|
|
|
if (depDetails.Any()) |
|
|
|
{ |
|
|
|
await _countJobManager.ImportAsync(job,depDetails, CurrentUser).ConfigureAwait(false); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 创建导入报告
|
|
|
|
var reportFile = ExportImportService.GetImportReport(inputFileBytes, modelDict); |
|
|
|
// 创建返回值
|
|
|
|
return new SfsImportResult |
|
|
|
{ |
|
|
|
TotalNum = modelList.Count, |
|
|
|
ErrorNum = modelDict.Count(o => o.Value.Any()), |
|
|
|
FileName = reportFile.FileDownloadName, |
|
|
|
FileContents = reportFile.FileContents |
|
|
|
}; |
|
|
|
} |
|
|
|
catch (Exception ex) |
|
|
|
{ |
|
|
|
Console.WriteLine("---------------------------------"); |
|
|
|
Console.WriteLine($"####导入验证错误:"); |
|
|
|
Console.WriteLine($"{ex.Message}"); |
|
|
|
Console.WriteLine("---------------------------------"); |
|
|
|
Logger.LogException(ex); |
|
|
|
if (modelList != null) |
|
|
|
{ |
|
|
|
try |
|
|
|
{ |
|
|
|
foreach (var item in modelDict) |
|
|
|
{ |
|
|
|
var model = item.Key; |
|
|
|
var validationRresults = item.Value; |
|
|
|
validationRresults.Add(new ValidationResult($"无法添加,{ex.Message}", new string[] { "异常" })); |
|
|
|
} |
|
|
|
|
|
|
|
// 创建导入报告
|
|
|
|
var reportFile = ExportImportService.GetImportReport(inputFileBytes, modelDict); |
|
|
|
return new SfsImportResult |
|
|
|
{ |
|
|
|
TotalNum = modelList.Count, |
|
|
|
ErrorNum = modelDict.Count(o => o.Value.Any()), |
|
|
|
FileName = reportFile.FileDownloadName, |
|
|
|
FileContents = reportFile.FileContents |
|
|
|
}; |
|
|
|
} |
|
|
|
catch (Exception) |
|
|
|
{ |
|
|
|
return new SfsImportResult() |
|
|
|
{ |
|
|
|
ExceptionMessage = ex.Message, |
|
|
|
FileContents = Encoding.Default.GetBytes(ex.Message) |
|
|
|
}; |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
return new SfsImportResult() |
|
|
|
{ |
|
|
|
ExceptionMessage = ex.Message, |
|
|
|
FileContents = Encoding.Default.GetBytes(ex.Message) |
|
|
|
}; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
/// <summary>
|
|
|
|
/// 导入验证
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="model"></param>
|
|
|
|
/// <param name="validationRresult"></param>
|
|
|
|
/// <param name="job"></param>
|
|
|
|
/// <param name="depDetail"></param>
|
|
|
|
/// <returns></returns>
|
|
|
|
protected async Task ValidateImportModelAsync(CountJobImportInput model, |
|
|
|
List<ValidationResult> validationRresult, CountJob job, CountJobDependentDetail depDetail) |
|
|
|
{ |
|
|
|
_ = new Dictionary<string, string>(); |
|
|
|
CheckJobNumberAsync(model, validationRresult, job.Number); |
|
|
|
_ = await CheckItemBasicAsync(model, validationRresult, depDetail).ConfigureAwait(false); |
|
|
|
_ = await CheckItemStoreRelationAsync(model, validationRresult,job.LocationCode).ConfigureAwait(false); |
|
|
|
_ = await CheckPackingCodeAsync(model, validationRresult, job.LocationCode).ConfigureAwait(false); |
|
|
|
} |
|
|
|
protected async Task<ItemBasicDTO> CheckItemBasicAsync(CountJobImportInput importInput, |
|
|
|
List<ValidationResult> validationRresult, CountJobDependentDetail depDetail) |
|
|
|
{ |
|
|
|
var item = await _itemBasicAppService.GetByCodeAsync(importInput.ItemCode).ConfigureAwait(false); |
|
|
|
if (item == null) |
|
|
|
{ |
|
|
|
validationRresult.Add(new ValidationResult($"物品代码{importInput.ItemCode}不存在", new[] { "物品代码" })); |
|
|
|
} |
|
|
|
else if (item.StdPackQty == 0) |
|
|
|
{ |
|
|
|
validationRresult.Add( |
|
|
|
new ValidationResult($"物品代码{importInput.ItemCode}的物品信息中标准包装等于0或不存在", new[] { "标准包装" })); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
depDetail.ItemName = item.Name; |
|
|
|
depDetail.ItemDesc1 = item.Desc1; |
|
|
|
depDetail.ItemDesc2 = item.Desc2; |
|
|
|
depDetail.StdPackQty = item.StdPackQty; |
|
|
|
depDetail.Uom = item.BasicUom; |
|
|
|
} |
|
|
|
return item; |
|
|
|
} |
|
|
|
|
|
|
|
protected async Task<ItemStoreRelationDTO> CheckItemStoreRelationAsync(CountJobImportInput importInput,List<ValidationResult> validationRresult,string locationCode) |
|
|
|
{ |
|
|
|
var item = await _itemStoreRelationAppService.GetByItemAndLocationAsync(importInput.ItemCode,locationCode,EnumStoreRelationType.Location).ConfigureAwait(false); |
|
|
|
if (item == null) |
|
|
|
{ |
|
|
|
validationRresult.Add(new ValidationResult($"零件与库位{locationCode}对应关系不存在", new[] { "物品代码" })); |
|
|
|
} |
|
|
|
return item; |
|
|
|
} |
|
|
|
protected async Task<BalanceDTO> CheckPackingCodeAsync(CountJobImportInput importInput, List<ValidationResult> validationRresult, string locationCode) |
|
|
|
{ |
|
|
|
if (!string.IsNullOrEmpty(importInput.PackingCode)) |
|
|
|
{ |
|
|
|
var item = await _balanceAppService.GetByPackingCodeAsync(importInput.PackingCode).ConfigureAwait(false); |
|
|
|
if (item != null) |
|
|
|
{ |
|
|
|
if (item.LocationCode != locationCode) |
|
|
|
{ |
|
|
|
validationRresult.Add(new ValidationResult($"箱码已经在库位{item.LocationCode}存在不能盘点", new[] { "箱码" })); |
|
|
|
} |
|
|
|
if (item.Lot != importInput.Lot) |
|
|
|
{ |
|
|
|
validationRresult.Add(new ValidationResult($"批次与库存中批次{item.Lot}不匹配不能盘点", new[] { "批次" })); |
|
|
|
} |
|
|
|
} |
|
|
|
return item; |
|
|
|
} |
|
|
|
|
|
|
|
return null; |
|
|
|
} |
|
|
|
protected void CheckJobNumberAsync(CountJobImportInput importInput, List<ValidationResult> validationRresult,string jobNumber) |
|
|
|
{ |
|
|
|
if (importInput.CountJobNumber != jobNumber) |
|
|
|
{ |
|
|
|
validationRresult.Add(new ValidationResult($"盘点任务单号{importInput.CountJobNumber}与其它有冲突,只允许导入一个任务单号数据", new[] { "盘点任务单号" })); |
|
|
|
} |
|
|
|
} |
|
|
|
#endregion
|
|
|
|
/// <summary>
|
|
|
|
/// 根据条件新增job接口
|
|
|
|
/// </summary>
|
|
|
@ -88,6 +284,7 @@ public class CountJobAppService |
|
|
|
} |
|
|
|
var entity = ObjectMapper.Map<CountJobDTO, CountJob>(dto); |
|
|
|
entity.Number = checkEntity.Number; |
|
|
|
|
|
|
|
await _countJobManager.CompleteAsync(entity, CurrentUser).ConfigureAwait(false); |
|
|
|
return dto; |
|
|
|
} |
|
|
|