Files
WMS-Api/src/WMS.Web.Domain/Services/ChangeMoveBoxService.cs
18942506660 0f25118b8b 修复bug
2024-03-01 10:07:30 +08:00

432 lines
20 KiB
C#

using AutoMapper;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WMS.Web.Core.Dto;
using WMS.Web.Core.Dto.ChangeBoxRecord;
using WMS.Web.Core.Dto.Inventory;
using WMS.Web.Core.Dto.Login;
using WMS.Web.Core.Dto.MoveBoxRecord;
using WMS.Web.Core.Help;
using WMS.Web.Core.Internal.Results;
using WMS.Web.Domain.Entitys;
using WMS.Web.Domain.Infrastructure;
using WMS.Web.Domain.IService;
using WMS.Web.Domain.IService.Public;
using WMS.Web.Domain.Values;
namespace WMS.Web.Domain.Services
{
///改箱 移箱服务
public class ChangeMoveBoxService : IChangeMoveBoxService
{
private readonly IMapper _mapper;
private readonly ILoginService _loginService;
private readonly IChangeBoxRecordRepositories _changeBoxRecordRepositories;
public readonly IBasicsRepositories _basbicsRepositories;
private readonly IMoveBoxRecordRepositories _moveBoxRecordRepositories;
private readonly IBoxRepositories _boxRepositories;
private readonly ISerialNumberService _serialNumberService;
private readonly IBoxInventoryService _boxInventoryService;
private readonly IBoxInventoryRepositories _boxInventoryRepositories;
private readonly ILogger<ChangeMoveBoxService> _logger;
private readonly ISerialNumbersRepositories _serialNumbersRepositories;
private readonly IBoxService _boxService;
public ChangeMoveBoxService(IMapper mapper, ILoginService loginService,
IChangeBoxRecordRepositories changeBoxRecordRepositories, IBasicsRepositories basbicsRepositories,
IMoveBoxRecordRepositories moveBoxRecordRepositories, IBoxRepositories boxRepositories,
ISerialNumberService serialNumberService, IBoxInventoryService boxInventoryService, IBoxInventoryRepositories boxInventoryRepositories,
ILogger<ChangeMoveBoxService> logger, ISerialNumbersRepositories serialNumbersRepositories, IBoxService boxService)
{
_mapper = mapper;
_loginService = loginService;
_changeBoxRecordRepositories = changeBoxRecordRepositories;
_basbicsRepositories = basbicsRepositories;
_moveBoxRecordRepositories = moveBoxRecordRepositories;
_boxRepositories = boxRepositories;
_serialNumberService = serialNumberService;
_boxInventoryService = boxInventoryService;
_boxInventoryRepositories = boxInventoryRepositories;
_logger = logger;
_serialNumbersRepositories = serialNumbersRepositories;
_boxService = boxService;
}
/// <summary>
/// 改箱保存
/// </summary>
/// <param name="dto"></param>
/// <param name="loginInfo"></param>
/// <returns></returns>
public async Task<Result> ChangeBoxSave(List<SaveChangeBoxRecordRequest> dto, LoginInDto loginInfo, bool isTransaction = false, bool IsInventory = true, bool IsPDA = false)
{
_logger.LogInformation($"改箱:{JsonConvert.SerializeObject(dto)} 操作人:{loginInfo.UserInfo.StaffId}");
bool isAddBox = false;
if (IsPDA)
{
//处理目标箱不在系统的情况,需要先增加箱信息
var d = dto.First();
if (d.DestBoxId == 0)
{
var dBox = await _boxRepositories.GetByNo(d.DestBoxBillNo);
if (dBox == null)
{
var res = await CreateBox(d);
if (!res.IsSuccess) return res;
dBox = await _boxRepositories.GetByNo(d.DestBoxBillNo);
dto.First().DestBoxId = dBox.Id;
isAddBox = true;
}
}
}
//1.有原箱时 需要判断 物料对应的序列号是否存在
var srcIds = dto.Select(s => s.SrcBoxId).Distinct().ToList();
var destIds = dto.Select(s => s.DestBoxId).Distinct().ToList();
var boxs = await _boxInventoryRepositories.GetList(srcIds);
var serialNumbers = dto.SelectMany(s => s.Details).SelectMany(s => s.SerialNumbers).ToList();
var serialNumberList = await _serialNumbersRepositories.GetEntityList(serialNumbers);
foreach (var d in dto)
{
if (d.SrcBoxId == 0)
{
//没有原箱的情况下需要验证序列号是否有箱子绑定
var s = d.Details.SelectMany(s => s.SerialNumbers).ToList();
var sCount = serialNumberList.Where(w => s.Contains(w.SerialNumber) && w.BoxId != 0).Count();
if (sCount > 0)
return Result.ReFailure(ResultCodes.SerialNumbersBoxError);
}
else
{
//有原箱的情况下验证序列号和原箱是否一致
var s = d.Details.SelectMany(s => s.SerialNumbers).ToList();
var boxCount = serialNumberList.Where(w => s.Contains(w.SerialNumber)).GroupBy(s => s.BoxId).Select(s => s.Key).ToList();
if (boxCount.Count() > 1 || (boxCount.Count() == 1 && boxCount[0] != d.SrcBoxId))
return Result.ReFailure(ResultCodes.SerialNumbersSrcBoxError);
}
var box = boxs.FirstOrDefault(f => f.BoxId == d.SrcBoxId);
//原箱在库存中的话 进行验证
if (box != null)
{
foreach (var bd in box.Details)
{
var bDe = box.Details.FirstOrDefault(f => f.MaterialId == bd.MaterialId);
if (bDe == null)
return Result.ReFailure(ResultCodes.BoxMateriaNoData);
var ex = bd.SerialNumbers.Except(bDe.SerialNumbers).ToList();
if (ex.Count() > 0)
return Result.ReFailure(ResultCodes.BoxInventorySerialNumbersNoData);
}
}
}
List<Box> boxList = new List<Box>();
//原箱有可能没有
var srcBoxs = await _boxRepositories.GetEntityList(srcIds);
var destBoxs = await _boxRepositories.GetEntityList(destIds);
//if (srcBox == null) return Result.ReFailure(ResultCodes.BoxNoData);
if (destBoxs.Count() != destIds.Count()) return Result.ReFailure(ResultCodes.BoxNoData);
foreach (var d in dto)
{
var l = d.Details.Select(s => (s.MaterialId, s.Qty, s.SerialNumbers)).ToList();
var srcBox = srcBoxs.FirstOrDefault(f => f.Id == d.SrcBoxId);
var destBox = destBoxs.FirstOrDefault(f => f.Id == d.DestBoxId);
//原箱移出
Result res;
if (srcBox != null)
{
res = srcBox.Out(l);
if (!res.IsSuccess) return res;
}
if (srcBox != null)
boxList.Add(srcBox);
//目标箱移入
if (!isAddBox)
{
res = destBox.In(l);
if (!res.IsSuccess) return res;
if (destBox != null)
boxList.Add(destBox);
}
}
List<ChangeBoxRecord> list = new List<ChangeBoxRecord>();
var subIds = dto.Select(s => s.SubStockId).ToList();
var subStocks = await _basbicsRepositories.GetSubUcStockAsync(subIds, loginInfo.UserInfo.CompanyId);
foreach (var dt in dto)
{
var subStock = subStocks.FirstOrDefault(f => f.Id == dt.SubStockId);
var boxi = boxs.FirstOrDefault(f => f.BoxId == dt.SrcBoxId);
foreach (var d in dt.Details)
{
ChangeBoxRecord entity = new ChangeBoxRecord();
entity.Create(loginInfo.UserInfo.StaffId, d.Qty, d.MaterialId, d.SerialNumbers, dt.SrcBoxId, dt.DestBoxId);
entity.SrcSubStockId = boxi?.SubStockId ?? 0;//原乡仓位需要去拉一下库存获取
if (subStock != null)
{
entity.DestSubStockId = dt.SubStockId;
entity.DestBoxOrgCode = subStock.ErpOrgCode;
entity.DestStockCode = subStock.StockCode;
}
list.Add(entity);
}
}
IDbContextTransaction _transaction = null;
if (isTransaction)
_transaction = _basbicsRepositories.GetTransaction();
Result res_Rollback = Result.ReSuccess();
bool isSuccess = true;
if (res_Rollback.IsSuccess)
{
isSuccess = await _changeBoxRecordRepositories.AddRange(list, false);
if (!isSuccess) res_Rollback = Result.ReFailure(ResultCodes.DateWriteError);
}
if (res_Rollback.IsSuccess)
{
var res_change = await _serialNumberService.ChangeBox(list, loginInfo, false);
if (!res_change.IsSuccess) res_Rollback = res_change;
}
if (res_Rollback.IsSuccess)
{
isSuccess = await _boxRepositories.EditEntityList(boxList, false);
if (!isSuccess) res_Rollback = Result.ReFailure(ResultCodes.DateWriteError);
}
if (res_Rollback.IsSuccess && IsInventory)
{
var res_Inventory = await _boxInventoryService.GenerateChangeBox(list, false);
if (!res_Inventory.IsSuccess) res_Rollback = res_Inventory;
}
//提交事务
if (isTransaction)
{
isSuccess = _basbicsRepositories.CommitTransaction(res_Rollback.IsSuccess ? false : true, _transaction);
if (!res_Rollback.IsSuccess) return res_Rollback;
if (!isSuccess)
return Result.ReFailure(ResultCodes.DateWriteError);
}
return Result.ReSuccess();
}
/// <summary>
/// 自动生成箱信息
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
private async Task<Result> CreateBox(SaveChangeBoxRecordRequest dto)
{
//增加一个空箱子
List<OpsBoxResponse> list = new List<OpsBoxResponse>();
OpsBoxResponse response = new OpsBoxResponse() { BoxBillNo = dto.DestBoxBillNo };
foreach (var d in dto.Details)
{
List<OpsSerialNumbersResponse> s = new List<OpsSerialNumbersResponse>();
foreach (var sd in d.SerialNumbers)
{
s.Add(new OpsSerialNumbersResponse() { SerialNumber = sd });
}
OpsBoxDetailsResponse dr = new OpsBoxDetailsResponse()
{
MaterialId = d.MaterialId,
Qty = d.Qty,
SerialNumbers = s
};
response.Details.Add(dr);
}
list.Add(response);
return await _boxService.Sync(list);
}
/// <summary>
/// 移箱保存
/// </summary>
/// <param name="dto"></param>
/// <param name="loginInfo"></param>
/// <returns></returns>
public async Task<Result> MoveBoxSave(List<SaveMoveBoxRecordRequest> dto, bool IsUp, LoginInDto loginInfo)
{
_logger.LogInformation($"移箱:{JsonConvert.SerializeObject(dto)} 是否上架:{IsUp} 操作人:{loginInfo.UserInfo.StaffId}");
//1.下架时 需要验证箱是否在库存里
var boxIds = dto.Select(s => s.BoxId).ToList();
var boxList = await _boxInventoryRepositories.GetList(boxIds);
if (!IsUp)
{
if (boxIds.Count() != boxList.Count())
return Result.ReFailure(ResultCodes.BoxInventoryNoDataError);
}
else
{
//上架时 箱子不能在库存里
if (boxList.Count() > 0)
{
var boxs = await _boxRepositories.GetEntityList(boxList.Select(s => s.BoxId).ToList());
return Result.ReFailure($"箱号{ string.Join(",", boxs.Select(s => s.BoxBillNo))} 已上架", 343433);
}
}
List<MoveBoxRecord> entityList = new List<MoveBoxRecord>();
foreach (var d in dto)
{
var subStock = await _basbicsRepositories.GetSubUcStockAsync(d.SubStockId, loginInfo.UserInfo.CompanyId);
var entity = new MoveBoxRecord();
entity.Create(IsUp == true ? MoveBoxType.Up : MoveBoxType.Down, d.BoxId, d.Qty, subStock?.ErpOrgCode, subStock?.StockCode, d.SubStockId, loginInfo.UserInfo.StaffId);
entity.Details = d.Details.Select(s => new MoveBoxRecordDetails()
{
MaterialId = s.MaterialId,
Qty = s.Qty,
SerialNumbers = s.SerialNumbers
}).ToList();
entityList.Add(entity);
}
IDbContextTransaction _transaction = _basbicsRepositories.GetTransaction();
bool isSuccess = true;
Result res_Rollback = Result.ReSuccess();
if (res_Rollback.IsSuccess)
{
isSuccess = await _moveBoxRecordRepositories.AddRange(entityList, false);
if (!isSuccess) res_Rollback = Result.ReFailure(ResultCodes.DateWriteError);
}
if (res_Rollback.IsSuccess)
{
var res_change = await _serialNumberService.MoveBox(entityList, loginInfo, false);
if (!res_change.IsSuccess) res_Rollback = res_change;
}
if (res_Rollback.IsSuccess)
{
var res_Inventory = await _boxInventoryService.GenerateMoveBox(entityList, false);
if (!res_Inventory.IsSuccess) res_Rollback = res_Inventory;
}
//提交事务
isSuccess = _basbicsRepositories.CommitTransaction(res_Rollback.IsSuccess ? false : true, _transaction);
if (!res_Rollback.IsSuccess) return res_Rollback;
if (!isSuccess)
return Result.ReFailure(ResultCodes.DateWriteError);
return Result.ReSuccess();
}
/// <summary>
/// 出入库回退改箱
/// </summary>
/// <param name="backRecord"></param>
/// <param name="loginInfo"></param>
/// <param name="isTransaction"></param>
/// <returns></returns>
public async Task<Result> ChangeBox_BackRecord(BackRecord backRecord, LoginInDto loginInfo, bool isTransaction = true)
{
if (backRecord.Method == InventoryInOutMethod.Box) return Result.ReSuccess();
List<SaveChangeBoxRecordRequest> dtoList = new List<SaveChangeBoxRecordRequest>();
var boxIds = backRecord.Details.Select(s => s.BoxId).Distinct().ToList();
var boxs = await _boxRepositories.GetEntityList(boxIds);
foreach (var d in backRecord.Details)
{
var box = boxs.FirstOrDefault(f => f.Id == d.BoxId);
if (box == null) continue;
if (backRecord.Type == BackRecordType.InstockOff)
box.BackRecordDown(d.MaterialId, d.Qty);
else
box.BackRecordUp(d.MaterialId, d.Qty);
}
IDbContextTransaction _transaction = null;
if (isTransaction)
_transaction = _basbicsRepositories.GetTransaction();
Result res_Rollback = Result.ReSuccess();
bool isSuccess = true;
if (res_Rollback.IsSuccess)
{
isSuccess = await _boxRepositories.EditEntityList(boxs, false);
if (!isSuccess) res_Rollback = Result.ReFailure(ResultCodes.DateWriteError);
}
//提交事务
if (isTransaction)
{
isSuccess = _basbicsRepositories.CommitTransaction(res_Rollback.IsSuccess ? false : true, _transaction);
if (!res_Rollback.IsSuccess) return res_Rollback;
if (!isSuccess)
return Result.ReFailure(ResultCodes.DateWriteError);
}
return Result.ReSuccess();
}
/// <summary>
/// 非采购入库
/// </summary>
/// <param name="inStock"></param>
/// <param name="loginInfo"></param>
/// <param name="isTransaction"></param>
/// <returns></returns>
public async Task<Result> ChangeBox_InStock(InStock inStock, LoginInDto loginInfo, bool isTransaction = true)
{
List<SaveChangeBoxRecordRequest> dtoList = new List<SaveChangeBoxRecordRequest>();
//目标箱
var destIds = inStock.Details.GroupBy(g => g.BoxId);
var serialNumbers = inStock.Details.SelectMany(s => s.SerialNumbers).ToList();
var serialNumberList = await _serialNumbersRepositories.GetEntityList(serialNumbers);
foreach (var detail in inStock.Details)
{
if (detail.Qty == 0) continue;
var detailClone = detail.Clone();
//处理序列号
var sList = serialNumberList.Where(w => detailClone.SerialNumbers.Contains(w.SerialNumber)).ToList();
foreach (var s in sList)
{
//原箱和目标箱一样不处理
if (s.BoxId == detailClone.BoxId)
{
detailClone.Qty = detailClone.Qty - 1;
detailClone.SerialNumbers.Remove(s.SerialNumber);
continue;
}
var d = dtoList.FirstOrDefault(f => f.DestBoxId == detailClone.BoxId && f.SrcBoxId == s.BoxId);
if (d == null)
{
d = new SaveChangeBoxRecordRequest(s.BoxId, detailClone.BoxId);
d.Details.Add(new SaveChangeBoxRecordDetailsRequest(detailClone.MaterialId, 1, s.SerialNumber));
}
else
{
var dtoDetail = d.Details.FirstOrDefault(f => f.MaterialId == detailClone.MaterialId);
if (dtoDetail == null)
d.Details.Add(new SaveChangeBoxRecordDetailsRequest(detailClone.MaterialId, 1, s.SerialNumber));
else
{
dtoDetail.Qty += 1;
dtoDetail.SerialNumbers.Add(s.SerialNumber);
}
}
detailClone.Qty = detailClone.Qty - 1;
detailClone.SerialNumbers.Remove(s.SerialNumber);
}
//处理非序列号的数据
if (detailClone.Qty <= 0) continue;
var dto = dtoList.FirstOrDefault(f => f.DestBoxId == detailClone.BoxId && f.SrcBoxId == 0);
if (dto == null)
{
dto = new SaveChangeBoxRecordRequest(0, detailClone.BoxId);
dto.Details.Add(new SaveChangeBoxRecordDetailsRequest(detailClone.MaterialId, detailClone.Qty, detailClone.SerialNumbers));
}
else
{
var dtoDetail = dto.Details.FirstOrDefault(f => f.MaterialId == detailClone.MaterialId);
if (dtoDetail == null)
dto.Details.Add(new SaveChangeBoxRecordDetailsRequest(detailClone.MaterialId, detailClone.Qty, detailClone.SerialNumbers));
else
{
dtoDetail.Qty += detailClone.Qty;
dtoDetail.SerialNumbers.AddRange(detailClone.SerialNumbers);
}
}
}
return await ChangeBoxSave(dtoList, loginInfo, isTransaction, false);
}
}
}