using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using JNPF.Common.Core.Manager;
using JNPF.Common.Filter;
using JNPF.EventBus;
using JNPF.Systems.Interfaces.System;
using JNPF.VisualDev;
using JNPF.VisualDev.Entitys.Dto.VisualDevModelData;
using JNPF.VisualDev.Interfaces;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using SqlSugar;
using Tnb.WarehouseMgr.Entities;
using Tnb.WarehouseMgr.Entities.Attributes;
using Tnb.WarehouseMgr.Entities.Entity;
using Tnb.WarehouseMgr.Interfaces;
using JNPF.Common.Dtos.VisualDev;
using JNPF.Common.Extension;
using JNPF.Common.Security;
using JNPF.FriendlyException;
using JNPF.VisualDev.Entitys;
using Microsoft.AspNetCore.Authorization;
using Tnb.BasicData.Entities;
using Tnb.WarehouseMgr.Entities.Consts;
using Tnb.WarehouseMgr.Entities.Dto;
using Tnb.WarehouseMgr.Entities.Enums;
using JNPF.Common.Enums;
using Tnb.WarehouseMgr.Entities.Dto.Inputs;
using Microsoft.Extensions.Logging;
using JNPF.Systems.Entitys.System;
using JNPF.Systems.Entitys.Permission;
namespace Tnb.WarehouseMgr
{
///
/// 原材料转库单
///
[OverideVisualDev(ModuleConsts.MODULE_WMSMATERIALTRANSFER_ID)]
[ServiceModule(BizTypeId)]
public class WmsMaterialTransferService : BaseWareHouseService
{
private const string BizTypeId = "";
private readonly ISqlSugarClient _db;
private readonly IRunService _runService;
private readonly IVisualDevService _visualDevService;
private readonly IWareHouseService _wareHouseService;
private readonly IBillRullService _billRullService;
private readonly IUserManager _userManager;
public WmsMaterialTransferService(
ISqlSugarRepository repository,
IRunService runService,
IVisualDevService visualDevService,
IWareHouseService wareHouseService,
IUserManager userManager,
IBillRullService billRullService,
IEventPublisher eventPublisher)
{
_db = repository.AsSugarClient();
_runService = runService;
_visualDevService = visualDevService;
_wareHouseService = wareHouseService;
_userManager = userManager;
_billRullService = billRullService;
OverideFuncs.GetListAsync = GetList;
}
[NonAction]
private async Task GetList(VisualDevModelListQueryInput input)
{
try
{
SqlSugarPagedList result = await _db.Queryable()
.InnerJoin((a, b) => a.status == b.Id)
.InnerJoin((a, b, c) => c.Id == a.create_id)
.InnerJoin((a, b, c, d) => d.id == a.warehouse_outstock)
.InnerJoin((a, b, c, d, e) => e.id == a.warehouse_instock)
.Select((a, b, c, d, e) => new WmsMaterialTransfer
{
id = a.id,
create_id = c.RealName,
create_time = a.create_time,
modify_id = a.modify_id,
modify_time = a.modify_time,
org_id = a.org_id,
tenant_id = a.tenant_id,
timestamp = a.timestamp,
bill_code = a.bill_code,
status = b.FullName,
bill_date = a.bill_date,
warehouse_outstock = d.whname,
warehouse_instock = d.whname,
type = a.type,
biller_out = a.biller_out,
depart_out = a.depart_out,
biller_in = a.biller_in,
depart_in = a.depart_in,
deliver_date = a.deliver_date,
arrival_date = a.arrival_date,
order_code = a.order_code,
})
.ToPagedListAsync(input.currentPage, input.pageSize);
var _data = PageResult.SqlSugarPageResult(result);
var json = JsonConvert.SerializeObject(_data);
var data = JsonConvert.DeserializeObject(json);
JArray mainTable = data.list;
foreach (dynamic row in mainTable)
{
row.deliver_date = row.deliver_date.Value.ToString("yyyy-MM-dd");
row.arrival_date = row.arrival_date.Value.ToString("yyyy-MM-dd");
row.create_time = row.create_time.Value.ToString("yyyy-MM-dd");
}
List wmsTransferInstockDs = _db.Queryable((a, b) =>
new JoinQueryInfos(JoinType.Left, a.material_id == b.id)
)
.Select((a, b) => new WmsMaterialTransferD
{
id = a.id,
material_id = a.material_id,
material_code = b.code,
material_ex = b.name,
material_specification = b.material_specification,
unit_id = a.unit_id,
unit_code = a.unit_code,
code_batch = a.code_batch,
station_code = a.station_code,
qty = a.qty,
yxfqty = a.yxfqty,
yzqty = a.yzqty,
bill_id = a.bill_id,
lineno = a.lineno,
f_flowtaskid = a.f_flowtaskid,
f_flowid = a.f_flowid,
})
.Where(a => mainTable.Select(r => r["id"].ToString()).ToList().Contains(a.bill_id)).ToList();
foreach (JObject wmsTransferInstockH in mainTable)
{
wmsTransferInstockH["tablefield121"] = JArray.Parse(JsonConvert.SerializeObject(wmsTransferInstockDs.Where(r => r.bill_id == wmsTransferInstockH["id"].ToString())));
}
return data;
}
catch (Exception ex)
{
return Task.FromResult(ex);
}
}
///
/// 获取物料库存
///
///
///
///
[HttpPost, NonUnify, AllowAnonymous]
public async Task MaterialInventory(MaterialTransferGetMaterialInventoryInput input)
{
try
{
if (input.palletCount <= 0)
{
throw new AppFriendlyException("托盘数必须大于0", 500);
}
if (string.IsNullOrEmpty(input.material_id))
{
throw new AppFriendlyException("物料id不可为空", 500);
}
if (string.IsNullOrEmpty(input.code_batch))
{
throw new AppFriendlyException("批号不可为空", 500);
}
//入库取终点 //出库起点
OutStockStrategyQuery inStockStrategyInput = new()
{
warehouse_id = WmsWareHouseConst.WAREHOUSE_YCL_ID,
material_id = input.material_id,
code_batch = input.code_batch,
Size = input.palletCount
};
List items = await _wareHouseService.OutStockStrategy(inStockStrategyInput);
decimal qty = _db.Queryable().Where(r => items.Select(a => a.id).Contains(r.carry_id) && r.material_id == input.material_id).Sum(r => r.codeqty);
JObject keyValuePairs = new JObject();
keyValuePairs["realPalletCount"] = items.Count;
keyValuePairs["realInvQty"] = qty;
return await ToApiResult(HttpStatusCode.OK, "成功", keyValuePairs);
}
catch (Exception ex)
{
await _db.Ado.RollbackTranAsync();
return await ToApiResult(HttpStatusCode.InternalServerError, ex.Message);
}
}
///
/// 按托下发
///
///
///
///
[HttpPost, NonUnify, AllowAnonymous]
public async Task Distribute(MaterialTransferDistributeInput input)
{
try
{
if (string.IsNullOrEmpty(input.source_id))
{
throw new AppFriendlyException("来源单据id不可为空", 500);
}
if (input.palletCount <= 0)
{
throw new AppFriendlyException("托盘数必须大于0", 500);
}
if (input.qty <= 0)
{
throw new AppFriendlyException("数量必须大于0", 500);
}
if (string.IsNullOrEmpty(input.code_batch))
{
throw new AppFriendlyException("批号不可为空", 500);
}
WmsMaterialTransferD wmsMaterialTransferD = await _db.Queryable().FirstAsync(it => it.id == input.source_id);
WmsMaterialTransfer wmsMaterialTransfer = await _db.Queryable().FirstAsync(it => it.id == wmsMaterialTransferD.bill_id);
await s_taskExecuteSemaphore.WaitAsync();
await _db.Ado.BeginTranAsync();
//入库取终点 //出库起点
OutStockStrategyQuery inStockStrategyInput = new() { warehouse_id = WmsWareHouseConst.WAREHOUSE_YCL_ID, material_id = wmsMaterialTransferD.material_id, code_batch = wmsMaterialTransferD.code_batch, Size = input.palletCount };
List items = await _wareHouseService.OutStockStrategy(inStockStrategyInput);
if (items.Count == 0)
{
throw new AppFriendlyException($@"没有可以出库的载具", 500);
}
decimal qty = _db.Queryable().Where(r => items.Select(a => a.id).Contains(r.carry_id) && r.material_id == wmsMaterialTransferD.material_id).Sum(r => r.codeqty);
// 暂定PDA上查询到的物料批次和库存数量与提交时获取的不一致时,需要前台重新获取库存接口
if (input.palletCount != items.Count || input.qty != qty)
{
throw new AppFriendlyException($@"当前实际托盘数量为{input.palletCount} 实际库存数量为{qty},与前台数据不一致,请重新获取库存", HttpStatusCode.InternalServerError);
}
foreach(var wmsCarryH in items)
{
WmsCarryCode wmsCarryCode = await _db.Queryable().Where(r => r.carry_id == wmsCarryH.id).FirstAsync();
BasLocation startLocation = await _db.Queryable().Where(r => r.location_code == wmsCarryH.location_code).FirstAsync();
BasLocation endLocation = null;
// 集中供料区三工位
if (wmsMaterialTransfer.warehouse_instock == WmsWareHouseConst.WAREHOUSE_JZGL_ID)
{
// 根据三工位任务数平均分配任务 暂定
endLocation = await _db.Queryable().Where(r => _wareHouseService.GetFloor1GLSGWOutstockLocation().Contains(r.id)).OrderBy("is_lock, task_nums, location_code").FirstAsync();
}
// 中储仓三工位
else if(wmsMaterialTransfer.warehouse_instock == WmsWareHouseConst.WAREHOUSE_ZC_ID)
{
// 根据三工位任务数平均分配任务 暂定
endLocation = await _db.Queryable().Where(r => _wareHouseService.GetFloor1WXSGWOutstockLocation().Contains(r.id)).OrderBy("is_lock, task_nums, location_code").FirstAsync();
}
CommonCreatePretaskInput commonCreatePretaskInput = new CommonCreatePretaskInput();
commonCreatePretaskInput.startlocation_id = startLocation.id;
commonCreatePretaskInput.endlocation_id = endLocation.id;
commonCreatePretaskInput.task_type = WmsWareHouseConst.WMS_PRETASK_OUTSTOCK_TYPE_ID;
commonCreatePretaskInput.biz_type = WmsWareHouseConst.BIZTYPE_WMSMATERIALTRANSFER_ID;
commonCreatePretaskInput.require_id = input.source_id;
Entities.Dto.Outputs.Result res = await _wareHouseService.CommonCreatePretask(commonCreatePretaskInput);
if (res.code != HttpStatusCode.OK)
{
Logger.LogInformation($@"生成预任务失败");
throw new AppFriendlyException($@"生成预任务失败", 500);
}
}
// 更新子表已下发数量
await _db.Updateable().SetColumns(r => r.yxfqty == r.yxfqty + input.qty).Where(r => r.id == input.source_id).ExecuteCommandAsync();
await _db.Ado.CommitTranAsync();
}
catch (Exception ex)
{
await _db.Ado.RollbackTranAsync();
return await ToApiResult(HttpStatusCode.InternalServerError, ex.Message);
}
finally
{
_ = s_taskExecuteSemaphore.Release();
await InvokeGenPretaskExcute();
}
return await ToApiResult(HttpStatusCode.OK, "成功");
}
public override async Task ModifyAsync(WareHouseUpInput input)
{
if (input == null)
{
throw new ArgumentNullException(nameof(input));
}
WmsCarryCode wmsCarryCode = await _db.Queryable().Where(r => r.carry_id == input.carryIds[0]).SingleAsync();
bool isOk = await _db.Updateable().SetColumns(it => new WmsMaterialTransferD { yzqty = it.yzqty + wmsCarryCode.codeqty })
.Where(it => it.id == input.requireId).ExecuteCommandHasChangeAsync();
if (!isOk)
{
throw Oops.Oh(ErrorCode.COM1001);
}
}
}
}