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

341 lines
17 KiB
C#

using System.Security.Cryptography.X509Certificates;
using JNPF.Common.Core.Manager;
using JNPF.Common.Dtos.VisualDev;
using JNPF.Common.Enums;
using JNPF.Common.Filter;
using JNPF.Common.Security;
using JNPF.FriendlyException;
using JNPF.VisualDev;
using JNPF.VisualDev.Entitys;
using JNPF.VisualDev.Entitys.Dto.VisualDevModelData;
using JNPF.VisualDev.Interfaces;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using NPOI.POIFS.Storage;
using SqlSugar;
using Tnb.BasicData.Entities;
using Tnb.ProductionMgr.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.Entity;
using Tnb.WarehouseMgr.Entities.Enums;
using Tnb.WarehouseMgr.Interfaces;
using JNPF.Common.Extension;
using JNPF.Systems.Interfaces.System;
namespace Tnb.WarehouseMgr
{
[OverideVisualDev(ModuleConsts.MODULE_WMSPACKINSTOCK_ID)]
[ServiceModule(BizTypeId)]
public class WmsPackInstockService : BaseWareHouseService, IWmsPackInstockService
{
private const string BizTypeId = WmsWareHouseConst.BIZTYPE_WMSPACKINSTOCK_ID;
private readonly ISqlSugarClient _db;
private readonly IRunService _runService;
private readonly IVisualDevService _visualDevService;
private readonly IUserManager _userManager;
private readonly IWareHouseService _wareHouseService;
private readonly IWmsCarryBindService _wmsCarryBindService;
private readonly IBillRullService _billRullService;
public static SemaphoreSlim s_packInstockSemaphore = new(1);
private readonly IWmsCarryService _wmsCarryService;
public WmsPackInstockService(
ISqlSugarRepository<WmsCarryH> repository,
IRunService runService,
IVisualDevService visualDevService,
IWareHouseService wareHouseService,
IUserManager userManager,
IWmsCarryBindService wmsCarryBindService,
IBillRullService billRullService,
IWmsCarryService wmsCarryService)
{
_db = repository.AsSugarClient();
_runService = runService;
_visualDevService = visualDevService;
_userManager = userManager;
_wareHouseService = wareHouseService;
_wmsCarryBindService = wmsCarryBindService;
_billRullService = billRullService;
_wmsCarryService = wmsCarryService;
}
public override async Task ModifyAsync(WareHouseUpInput input)
{
if (input == null)
{
throw new ArgumentNullException(nameof(input));
}
try
{
//if (input.wmsDistaskH.start_floor == 4 && input.wmsDistaskH.end_floor == 4)
{
WmsCarryCode wmsCarryCode = await _db.Queryable<WmsCarryCode>().Where(r => r.carry_id == input.wmsDistaskH.carry_id).FirstAsync();
await _db.Updateable<WmsPackInstockD>().SetColumns(r => r.qty == r.qty + wmsCarryCode.codeqty).Where(r => r.id == input.wmsDistaskH.require_id).ExecuteCommandAsync();
WmsPackInstockD wmsPackInstockD = await _db.Queryable<WmsPackInstockD>().Where(r => r.id == input.wmsDistaskH.require_id).FirstAsync();
if (wmsPackInstockD != null)
{
int row = await _db.Updateable<WmsCarryCode>().SetColumns(r => new WmsCarryCode
{
auxprop_gys = wmsPackInstockD.auxprop_gys,
auxprop_xph = wmsPackInstockD.auxprop_xph
}).Where(r => r.carry_id == input.wmsDistaskH.carry_id).ExecuteCommandAsync();
}
else
{
throw new Exception($"【WmsPackInstockService ModifyAsync】id为{input.wmsDistaskH.require_id}的包材入库明细在系统中不存在");
}
}
}
catch (Exception ex)
{
Logger.LogWarning("【WmsPackInstockService ModifyAsync】" + ex.Message);
Logger.LogWarning("【WmsPackInstockService ModifyAsync】" + ex.StackTrace);
}
}
[HttpPost, NonUnify, AllowAnonymous]
public async Task<dynamic> List(TransferInstockHListInput input)
{
try
{
JObject jobject = new JObject();
jobject["code"] = "200";
List<WmsPackInstockD> wmsPackInstockD = _db.Queryable<WmsPackInstockD>().Where(r => r.bill_id == input.id && r.status != WmsWareHouseConst.TASK_BILL_STATUS_COMPLE_ID).ToList();
jobject["data"] = JArray.Parse(JsonConvert.SerializeObject(wmsPackInstockD));
return await Task.FromResult(jobject);
}
catch (Exception ex)
{
return Task.FromResult(ex);
}
}
/// <summary>
/// 1楼到4楼 包材入库
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
/// <exception cref="AppFriendlyException"></exception>
[HttpPost, NonUnify, AllowAnonymous]
public async Task<Tnb.WarehouseMgr.Entities.Dto.Outputs.Result> PackInstock(OutsourcedPartsInstockInput input)
{
try
{
if (string.IsNullOrEmpty(input.carry_code))
{
throw new AppFriendlyException("载具编号不可为空", 500);
}
if (string.IsNullOrEmpty(input.material_id))
{
throw new AppFriendlyException("物料id不可为空", 500);
}
if (input.qty <= 0)
{
throw new AppFriendlyException("数量必须大于0", 500);
}
if (string.IsNullOrEmpty(input.source_id))
{
throw new AppFriendlyException("包材入库明细id不可为空", 500);
}
if (string.IsNullOrEmpty(input.startlocation_id))
{
throw new AppFriendlyException("起点不可为空", 500);
}
WmsPackInstockD wmsPackInstockD = await _db.Queryable<WmsPackInstockD>().Where(r => r.id == input.source_id).FirstAsync();
if (wmsPackInstockD.status == WmsWareHouseConst.TASK_BILL_STATUS_COMPLE_ID)
{
throw new AppFriendlyException("此包材入库任务已完成,不允许重复提交", 500);
}
await s_packInstockSemaphore.WaitAsync();
await _db.Ado.BeginTranAsync();
//入库取终点 //出库起点
InStockStrategyQuery inStockStrategyInput = new() { warehouse_id = WmsWareHouseConst.WAREHOUSE_BCK_ID, Size = 1 };
List<BasLocation> endLocations = await _wareHouseService.InStockStrategy(inStockStrategyInput);
if (endLocations.Count == 0)
{
throw new AppFriendlyException("没有可用的入库库位", 500);
}
WmsPointH sPoint = null!;
WmsPointH ePoint = null!;
sPoint = await _db.Queryable<WmsPointH>().FirstAsync(it => it.location_id == input.startlocation_id);
if (endLocations?.Count > 0)
{
WmsCarryH carry = await _db.Queryable<WmsCarryH>().SingleAsync(it => it.carry_code == input.carry_code);
//if (carry.carry_status == "1")
//{
// throw new AppFriendlyException("载具已占用!", 500);
//}
if (carry.is_lock == 1)
{
throw new AppFriendlyException("载具已锁定!", 500);
}
BasLocation loc = await _db.Queryable<BasLocation>().SingleAsync(it => it.id == endLocations[0].id);
bool isMatch = await IsCarryAndLocationMatchByCarryStd(carry, loc);
if (!isMatch)
{
throw new AppFriendlyException("库位与载具规格不匹配", 500);
}
ePoint = await _db.Queryable<WmsPointH>().FirstAsync(it => it.location_id == endLocations[0].id);
}
else
{
throw new AppFriendlyException($"库位{endLocations[0].location_code}未在点位表中维护对应点位", 500);
}
string endLocationId = endLocations[0].id;
// 计算路径,插入预任务申请
if (sPoint != null && ePoint != null)
{
List<WmsPointH> points = new List<WmsPointH>();
if (sPoint.area_code != ePoint.area_code)
{
points = await _wareHouseService.PathAlgorithms(sPoint.id, ePoint.id);
Logger.LogError($"【PackInstock】 选择了 {sPoint.point_code} {ePoint.point_code}");
if (points.Count <= 2)
{
throw new AppFriendlyException($"sPoint {sPoint.point_code} ePoint{ePoint.point_code}该路径不存在", 500);
}
}
else
{
points.Add(sPoint);
points.Add(ePoint);
}
WmsCarryH wmsCarryH = await _db.Queryable<WmsCarryH>().FirstAsync(it => it.carry_code == input.carry_code);
//根据获取的路径点生成预任务,生成顺序必须预路径算法返回的起终点的顺序一致(预任务顺序)
if (points?.Count > 0)
{
List<WmsPretaskH> preTasks = points.Where(it => !it.location_id.IsNullOrEmpty()).GroupBy(g => g.area_code).Select(it =>
{
WmsPointH? sPoint = it.FirstOrDefault();
WmsPointH? 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 = WmsWareHouseConst.BIZTYPE_WMSPACKINSTOCK_ID,
task_type = WmsWareHouseConst.WMS_PRETASK_TRANSFER_TYPE_ID
};
preTask.carry_id = wmsCarryH.id;
preTask.carry_code = wmsCarryH.carry_code;
preTask.area_id = sPoint?.area_id!;
preTask.area_code = it.Key;
preTask.require_id = input.source_id;
preTask.require_code = "";
preTask.create_id = _userManager.UserId;
preTask.create_time = DateTime.Now;
return preTask;
}).ToList();
bool isOk = await _wareHouseService.GenPreTask(preTasks, null!, _db);
if (isOk)
{
if (endLocationId != null)
{
//查询库位表
BasLocation location = await _db.Queryable<BasLocation>().SingleAsync(it => it.id == input.startlocation_id);
{
//载具加锁,增加库位信息
_ = await _db.Updateable<WmsCarryH>().SetColumns(it => new WmsCarryH
{
carry_status = ((int)EnumCarryStatus.).ToString(),
is_lock = 1,
location_id = input.startlocation_id,
location_code = location.location_code
}).Where(it => it.id == wmsCarryH.id).ExecuteCommandAsync();
}
//所有库位加锁
string?[] ids = new[] { input.startlocation_id, endLocationId };
_ = await _db.Updateable<BasLocation>().SetColumns(it => new BasLocation { is_lock = 1 }).Where(it => ids.Contains(it.id)).ExecuteCommandAsync();
BasMaterial basMaterial = await _db.Queryable<BasMaterial>().FirstAsync(it => it.id == input.material_id);
BindCarryCodeInput bindCarryCodeInput = new BindCarryCodeInput();
bindCarryCodeInput.carry_id = wmsCarryH.id;
bindCarryCodeInput.barcode = wmsCarryH.carry_code;
bindCarryCodeInput.codeqty = input.qty;
bindCarryCodeInput.material_id = input.material_id;
bindCarryCodeInput.material_code = basMaterial.code;
bindCarryCodeInput.material_name = basMaterial.name;
bindCarryCodeInput.location_id = endLocations[0].id;
bindCarryCodeInput.location_code = endLocations[0].location_code;
bindCarryCodeInput.code_batch = wmsPackInstockD.pi_code;
bindCarryCodeInput.unit_id = basMaterial.unit_id;
await _wmsCarryService.BindCarryMaterial(bindCarryCodeInput);
}
}
}
}
// 更新包材入库单子表已下发数量
await _db.Updateable<WmsPackInstockD>().SetColumns(r => r.xf_qty == r.xf_qty + input.qty).Where(r => r.id == input.source_id).ExecuteCommandAsync();
// 已下发数量达到需求数量回写已完成
wmsPackInstockD = await _db.Queryable<WmsPackInstockD>().Where(r => r.id == input.source_id).FirstAsync();
if (wmsPackInstockD.xf_qty == wmsPackInstockD.pr_qty)
{
await _db.Updateable<WmsPackInstockD>().SetColumns(r => r.status == WmsWareHouseConst.TASK_BILL_STATUS_COMPLE_ID).Where(r => r.id == input.source_id).ExecuteCommandAsync();
}
// 入库明细都完成 回写主表完成状态
List<WmsPackInstockD> wmsPackInstockDs = _db.Queryable<WmsPackInstockD>().InnerJoin<WmsPackInstockD>((a, b) => a.bill_id == b.bill_id).Where((a, b) => a.id == input.source_id)
.Where((a, b) => b.status != WmsWareHouseConst.TASK_BILL_STATUS_COMPLE_ID).ToList();
if (wmsPackInstockDs.Count == 0)
{
await _db.Updateable<WmsPackInstockH>().SetColumns(r => r.status == WmsWareHouseConst.TASK_BILL_STATUS_COMPLE_ID).Where(r => r.id == wmsPackInstockD.bill_id).ExecuteCommandAsync();
}
await _db.Ado.CommitTranAsync();
}
catch (Exception ex)
{
Logger.LogError($"【PackInstock】 {ex.Message}");
Logger.LogError($"【PackInstock】 {ex.StackTrace}");
await _db.Ado.RollbackTranAsync();
return await ToApiResult(HttpStatusCode.InternalServerError, ex.Message);
}
finally
{
_ = s_packInstockSemaphore.Release();
await InvokeGenPretaskExcute();
}
return await ToApiResult(HttpStatusCode.OK, "成功");
}
}
}