Files
tnb.server/WarehouseMgr/Tnb.WarehouseMgr/WmskittingOutService.cs

454 lines
23 KiB
C#

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using System.Linq.Expressions;
using System.Net.Http;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using System.Transactions;
using Aop.Api.Domain;
using JNPF;
using JNPF.Common.Const;
using JNPF.Common.Core.Manager;
using JNPF.Common.Dtos.VisualDev;
using JNPF.Common.Enums;
using JNPF.Common.Extension;
using JNPF.Common.Manager;
using JNPF.Common.Security;
using JNPF.DataEncryption;
using JNPF.FriendlyException;
using JNPF.LinqBuilder;
using JNPF.Logging;
using JNPF.Systems.Entitys.Permission;
using JNPF.Systems.Interfaces.System;
using Mapster;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using SqlSugar;
using Tnb.BasicData.Entities;
using Tnb.WarehouseMgr.Entities;
using Tnb.WarehouseMgr.Entities.Attributes;
using Tnb.WarehouseMgr.Entities.Consts;
using Tnb.WarehouseMgr.Entities.Dto;
using Tnb.WarehouseMgr.Entities.Dto.Inputs;
using Tnb.WarehouseMgr.Entities.Dto.Outputs;
using Tnb.WarehouseMgr.Entities.Enums;
using Tnb.WarehouseMgr.Entities.Exceptions;
using Tnb.WarehouseMgr.Interfaces;
namespace Tnb.WarehouseMgr
{
/// <summary>
/// 齐套出库服务类
/// </summary>
[ServiceModule(BizTypeId)]
public class WmskittingOutService : BaseWareHouseService, IWmskittingOutService
{
private readonly ISqlSugarClient _db;
private readonly IWareHouseService _warehouseService;
private readonly IUserManager _userManager;
private readonly IBillRullService _billRullService;
private readonly IWmsCarryService _carryService;
private readonly ICacheManager _cacheManager;
private const string BizTypeId = "26169472620837";
public WmskittingOutService(
ISqlSugarRepository<WmsKittingoutH> repository,
IWareHouseService warehouseService,
IUserManager userManager,
IBillRullService billRullService,
IWmsCarryService carryService,
ICacheManager cacheManager,
ITaskMessageNotify taskMessageNotify
) : base(taskMessageNotify.Writer)
{
_db = repository.AsSugarClient();
_warehouseService = warehouseService;
_userManager = userManager;
_billRullService = billRullService;
_carryService = carryService;
_cacheManager = cacheManager;
}
/// <summary>
/// 齐套出库(新增状态)
/// </summary>
/// <returns></returns>
[HttpPost, Timed(Name = nameof(KittingOutByAdd))]
public async Task KittingOutByAdd(CancellationToken? ct = default)
{
//if (UserManager.AsscessToken.IsNullOrWhiteSpace()) return;
//var curUser = await GetUserIdentity();
if (ct?.IsCancellationRequested ?? false)
{
ct?.ThrowIfCancellationRequested();
}
var curDb = _db.CopyNew();
try
{
await curDb.Ado.BeginTranAsync();
var kittingOuts = await curDb.Queryable<WmsKittingoutH>()
.Where(a => a.status == WmsWareHouseConst.BILLSTATUS_ADD_ID)
.OrderBy(a => a.seq)
.ToListAsync();
// 是否有已呼叫的齐套出库任务
// var set = true ; 如果有 把set修改为false
var items = await curDb.Queryable<WmsKittingoutH>().Where(it => it.status == WmsWareHouseConst.BILLSTATUS_CALLED_ID).ToListAsync();
var isCalled = items?.Count > 0;
if (kittingOuts?.Count > 0)
{
foreach (var ko in kittingOuts)
{
//a.carrystd_id == WmsWareHouseConst.CARRY_LJSTD_ID
Expression<Func<WmsCarryH, bool>> whereExp = (ko.carry_id != null) ? a => a.id == ko.carry_id : a => a.carrystd_id == WmsWareHouseConst.CARRY_LJSTD_ID;
var carrys = await curDb.Queryable<WmsCarryH>()
.InnerJoin<WmsCollocationSchemeH>((a, b) => a.collocation_scheme_id == b.id)
.Where(whereExp.And(a => a.collocation_scheme_id == ko.collocation_scheme_id && a.is_lock == 0))
.OrderBy((a, b) => b.seq)
.ToListAsync();
if (carrys?.Count > 0)
{
var firstCarry = carrys.FirstOrDefault();
GenPreTaskUpInput genPreTaskInput = new() { CarryId = firstCarry?.id };
await _warehouseService.GenInStockTaskHandleAfter(genPreTaskInput, it => new WmsCarryH { is_lock = 1, out_status = EnumOutStatus..ToString() }, null!);
ko.status = WmsWareHouseConst.BILLSTATUS_TOBESHIPPED_ID;
ko.carry_id = firstCarry?.id;
ko.carry_code = firstCarry?.carry_code;
await _db.Updateable(ko).UpdateColumns(it => new { it.status, it.carry_id, it.carry_code }).ExecuteCommandAsync();
//await KittingOutByIsToBeShipped();
if (firstCarry != null)
{
firstCarry.source_id = ko.source_id;
firstCarry.source_code = ko.source_code;
await _db.Updateable(firstCarry).UpdateColumns(it => new { it.source_id, it.source_code }).ExecuteCommandAsync();
}
}
else
{
//if(false) 跳出 插入完一次齐套分拣 set 改为false
if (!isCalled)
{
var setSortingH = ko.Adapt<WmsSetsortingH>();
setSortingH.warehouse_id = WmsWareHouseConst.WAREHOUSE_ZC_ID;
setSortingH.id = SnowflakeIdHelper.NextId();
setSortingH.kittingout_id = ko.id;
setSortingH.seq = ko.seq;
setSortingH.org_id = _userManager.User.OrganizeId;
setSortingH.create_id = _userManager.UserId;
setSortingH.create_time = DateTime.Now;
await curDb.Insertable(setSortingH).ExecuteCommandAsync();
var kittingOutDetails = await curDb.Queryable<WmsKittingoutD>().Where(it => it.bill_id == ko.id).ToListAsync();
var setSortDetails = kittingOutDetails.Adapt<List<WmsSetsortingD>>();
setSortDetails.ForEach(x =>
{
x.id = SnowflakeIdHelper.NextId();
x.bill_id = setSortingH.id;
x.warehouse_id = setSortingH.warehouse_id;
x.org_id = _userManager.User.OrganizeId;
x.create_id = _userManager.UserId;
x.create_time = DateTime.Now;
});
await curDb.Insertable(setSortDetails).ExecuteCommandAsync();
ko.status = WmsWareHouseConst.BILLSTATUS_CALLED_ID;
await curDb.Updateable(ko).UpdateColumns(it => it.status).ExecuteCommandAsync();
isCalled = true;
//await Publish(nameof(IWmsSetSortingService.PackSortingByAdd));
}
}
}
}
await curDb.Ado.CommitTranAsync();
}
catch (Exception ex)
{
Log.Error("齐套出库,新增时出现错误", ex);
await curDb.Ado.RollbackTranAsync();
TimedTaskErrorInfo ei = new()
{
RequestURL = App.HttpContext?.Request?.Path,
RequestMethod = App.HttpContext?.Request?.Method,
userIdentity = await GetUserIdentity(_userManager.ToKen),
};
var timedTaskEx = ex.ToTimedTaskException(ei);
//cts?.Cancel();
throw timedTaskEx;
}
}
/// <summary>
/// 齐套出库,(待配送状态)
/// </summary>
/// <returns></returns>
[HttpPost, Timed(Name = nameof(KittingOutByIsToBeShipped))]
public async Task KittingOutByIsToBeShipped(CancellationToken? ct = default)
{
//if (UserManager.AsscessToken.IsNullOrWhiteSpace()) return;
//var curUser = await GetUserIdentity();
var curDb = _db.CopyNew();
try
{
var kittingOuts = await curDb.Queryable<WmsKittingoutH>()
.Where(a => a.status == WmsWareHouseConst.BILLSTATUS_TOBESHIPPED_ID)
.OrderBy(a => a.seq)
.ToListAsync();
if (kittingOuts?.Count > 0)
{
var grpList = kittingOuts.GroupBy(g => g.location_id).ToList();
foreach (var koGrp in grpList)
{
var locs = await curDb.Queryable<BasLocation>().Where(it => it.id == koGrp.Key && it.is_use == ((int)EnumCarryStatus.).ToString() && it.is_lock == 0).ToListAsync();
if (locs?.Count > 0)
{
var arr = koGrp.ToArray();
var ko = arr[^arr.Length];
var carry = await curDb.Queryable<WmsCarryH>().SingleAsync(it => it.id == ko.carry_id);
if (carry != null)
{
WmsPointH sPoint = await curDb.Queryable<WmsPointH>().FirstAsync(it => it.location_id == carry.location_id);
WmsPointH ePoint = await curDb.Queryable<WmsPointH>().FirstAsync(it => it.location_id == ko.location_id);
if (sPoint != null && ePoint != null)
{
//判断目标库位是否自动签收
var loc = await curDb.Queryable<BasLocation>().SingleAsync(it => it.id == ePoint.location_id);
var points = await _warehouseService.PathAlgorithms(sPoint.id, ePoint.id);
if (points.Count <= 2) throw new AppFriendlyException("该路径不存在", 500);
if (points?.Count > 0)
{
var preTasks = points.Where(it => !it.location_id.IsNullOrEmpty()).GroupBy(g => g.area_code).Select(it =>
{
var sPoint = it.FirstOrDefault();
var ePoint = it.LastOrDefault();
WmsPretaskH preTask = new()
{
org_id = _userManager.User.OrganizeId,
startlocation_id = sPoint?.location_id!,
startlocation_code = sPoint?.location_code!,
endlocation_id = ePoint?.location_id!,
endlocation_code = ePoint?.location_code!,
start_floor = sPoint?.floor.ToString(),
end_floor = ePoint?.floor.ToString(),
startpoint_id = sPoint?.id!,
startpoint_code = sPoint?.point_code!,
endpoint_id = ePoint?.id!,
endpoint_code = ePoint?.point_code!,
bill_code = _billRullService.GetBillNumber(WmsWareHouseConst.WMS_PRETASK_H_ENCODE).GetAwaiter().GetResult(),
status = WmsWareHouseConst.PRETASK_BILL_STATUS_DXF_ID,
biz_type = ko.biz_type,
task_type = WmsWareHouseConst.WMS_PRETASK_OUTSTOCK_TYPE_ID,
carry_id = ko!.carry_id!,
carry_code = ko!.carry_code!,
area_id = sPoint?.area_id!,
area_code = it.Key,
require_id = ko.id,
require_code = ko.bill_code,
create_id = _userManager.UserId,
create_time = DateTime.Now,
source_id = ko.source_id,
source_code = ko.source_code
};
return preTask;
}).ToList();
if (loc.is_sign == 0)
{
preTasks[^1].is_sign = 0; // 修改最后一个元素的是否签收值
}
await _warehouseService.GenPreTask(preTasks, null!);
var subCarrys = await curDb.Queryable<WmsCarryD>().Where(it => it.carry_id == ko.carry_id).ToListAsync();
var carryIds = subCarrys.Select(x => x.carry_id).Concat(new[] { ko.carry_id }).Distinct().ToList();
GenPreTaskUpInput genPreTaskInput = new() { CarryIds = carryIds!, LocationIds = new List<string> { carry.location_id!, ko.location_id! } };
await _warehouseService.GenInStockTaskHandleAfter(genPreTaskInput, it => new WmsCarryH { is_lock = 1, carry_status = ((int)EnumCarryStatus.).ToString() }, it => new BasLocation { is_lock = 1 });
await curDb.Updateable<WmsKittingoutH>().SetColumns(it => it.status == WmsWareHouseConst.BILLSTATUS_ON_ID).Where(it => it.id == ko.id).ExecuteCommandAsync();
}
}
}
}
}
}
}
catch (Exception ex)
{
Log.Error("齐套出库,待配送时出现错误", ex);
await curDb.Ado.RollbackTranAsync();
TimedTaskErrorInfo ei = new()
{
RequestURL = App.HttpContext?.Request?.Path,
RequestMethod = App.HttpContext?.Request?.Method,
userIdentity = await GetUserIdentity(_userManager.ToKen),
};
var timedTaskEx = ex.ToTimedTaskException(ei);
//cts?.Cancel();
throw timedTaskEx;
}
finally
{
await Publish(nameof(IWareHouseService.GenTaskExecute));
}
}
public override async Task ModifyAsync(WareHouseUpInput input)
{
if (input == null) throw new ArgumentNullException(nameof(input));
try
{
await _db.Ado.BeginTranAsync();
var carryId = input.carryIds[^input.carryIds.Count];
var carry = await _db.Queryable<WmsCarryH>().SingleAsync(it => it.id == carryId);
var kods = await _db.Queryable<WmsKittingoutD>().Where(it => it.bill_id == input.requireId).ToListAsync();
//载具为料架时,取所有料箱的条码
List<string> mCarryIds = new();
if (carry.carrystd_id == WmsWareHouseConst.CARRY_LJSTD_ID)
{
var carryDs = await _db.Queryable<WmsCarryD>().Where(it => it.carry_id == carryId).ToListAsync();
mCarryIds = carryDs.Select(x => x.membercarry_id).ToList();
}
//当前载具对应的所有条码插入
Expression<Func<WmsCarryCode, bool>> whereExp = mCarryIds?.Count > 0 ? a => mCarryIds.Contains(a.carry_id) : a => a.carry_id == carryId;
var carryCodes = await _db.Queryable<WmsCarryCode>().Where(whereExp).ToListAsync();
var kittingoutCodes = carryCodes.Adapt<List<WmsKittingoutCode>>();
kittingoutCodes.ForEach(x =>
{
var billDId = kods?.Find(xx => xx.material_id == x.material_id && xx.code_batch == x.code_batch)?.id;
if (billDId.IsNullOrEmpty())
{
billDId = kods?.Find(xx => xx.material_id == x.material_id)?.id;
}
x.id = SnowflakeIdHelper.NextId();
x.bill_id = input.requireId;
x.bill_d_id = billDId!;
x.org_id = _userManager.User.OrganizeId;
x.create_id = _userManager.UserId;
x.create_time = DateTime.Now;
});
var row = await _db.Insertable(kittingoutCodes).ExecuteCommandAsync();
var detailIds = kittingoutCodes.Select(x => x.bill_d_id).ToList();
var curKittingoutDetails = kods.FindAll(x => detailIds.Contains(x.id));
var dic = kittingoutCodes.GroupBy(g => g.bill_d_id).ToDictionary(x => x.Key, x => x.Select(x => x.codeqty).ToList());
foreach (var kod in curKittingoutDetails)
{
if (dic.ContainsKey(kod.id))
{
kod.qty += dic[kod.id].Sum(d => d);
if (kod.qty >= kod.pr_qty)
{
kod.line_status = WmsWareHouseConst.BILLSTATUS_COMPLETE_ID;
}
else
{
kod.line_status = WmsWareHouseConst.BILLSTATUS_ON_ID;
}
}
}
await _db.Updateable(curKittingoutDetails).ExecuteCommandAsync();
var isOk = await _db.Updateable<WmsKittingoutH>().SetColumns(it => new WmsKittingoutH { status = WmsWareHouseConst.BILLSTATUS_COMPLETE_ID }).Where(it => it.id == input.requireId).ExecuteCommandHasChangeAsync();
//if (carry != null)
//{
// row = await _carryService.UpdateNullCarry(carry);
// isOk = row > 0;
//}
//判断当前载具是否为料架,如果是料架 清空所有料架/料箱数据,
if (carry.carrystd_id == WmsWareHouseConst.CARRY_LJSTD_ID && mCarryIds?.Count > 0)
{
var carrys = await _db.Queryable<WmsCarryH>().Where(it => mCarryIds.Contains(it.id)).ToListAsync();
carrys.Add(carry);
if (carrys?.Count > 0)
{
await _db.Ado.BeginTranAsync();
var tasks = new List<Task<Task<int>>>();
Func<WmsCarryH, Task<int>>? upateNullCarryFunc = carryIt => Task.Run(() => _db.CopyNew().Updateable(carryIt).ExecuteCommandAsync());
foreach (var carryIt in carrys)
{
tasks.Add(_carryService.UpdateNullCarry(carryIt, upateNullCarryFunc));
}
var all = await Task.WhenAll(tasks.Select(t => t.Unwrap()));
if (all.All(x => x > 0))
{
isOk = all?.Length > 0;
}
await _db.Ado.CommitTranAsync();
}
}
if (!isOk) throw Oops.Oh(ErrorCode.COM1001);
await _db.Ado.CommitTranAsync();
}
catch (Exception)
{
await _db.Ado.RollbackTranAsync();
throw;
}
}
/// <summary>
/// MES齐套出库接口
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[HttpPost]
public async Task<dynamic> MESKittingOutStk(List<MESKittingOutStkInput> input)
{
var isSuccessFul = false;
if (input.IsNull()) throw new ArgumentNullException(nameof(input));
try
{
await _db.Ado.BeginTranAsync();
List<WmsKittingoutD> kittingOutDs = new();
var kittingOuts = input.Adapt<List<WmsKittingoutH>>();
var ids = input.Select(x => x.location_code).ToArray();
for (int i = 0; i < kittingOuts.Count; i++)
{
var x = kittingOuts[i];
x.id = SnowflakeIdHelper.NextId();
x.bill_code = _billRullService.GetBillNumber(WmsWareHouseConst.WMS_KITTINGOUTSTK_ENCODE).GetAwaiter().GetResult();
x.bill_date = DateTime.Now;
x.bill_type = WmsWareHouseConst.BIZTYPE_WMSKITTINGOUTSTK_ID;
x.status = WmsWareHouseConst.BILLSTATUS_ADD_ID;
x.biz_type = WmsWareHouseConst.BIZTYPE_WMSKITTINGOUTSTK_ID;
x.location_id = ids[i];
var d = input[i]?.wmsKittingoutDs?.Adapt<List<WmsKittingoutD>>();
d?.ForEach(it =>
{
it.id = SnowflakeIdHelper.NextId();
it.bill_id = x.id;
it.qty = 0;
it.real_box = 0;
it.warehouse_id = x.warehouse_id;
});
if (d != null)
{
kittingOutDs.AddRange(d);
}
}
await _db.Insertable(kittingOuts).ExecuteCommandAsync();
await _db.Insertable(kittingOutDs).ExecuteCommandAsync();
await _db.Ado.CommitTranAsync();
await KittingOutByAdd();
isSuccessFul = true;
}
catch (Exception ex)
{
Log.Error("MES齐套出库接口出错", ex);
isSuccessFul = false;
await _db.Ado.RollbackTranAsync();
}
return isSuccessFul;
}
}
}