294 lines
14 KiB
C#
294 lines
14 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using System.Text;
|
||
using System.Threading.Tasks;
|
||
using Aop.Api.Domain;
|
||
using JNPF.Common.Core.Manager;
|
||
using JNPF.Common.Enums;
|
||
using JNPF.Common.Security;
|
||
using JNPF.EventBus;
|
||
using JNPF.FriendlyException;
|
||
using JNPF.Systems.Entitys.System;
|
||
using JNPF.Systems.Interfaces.System;
|
||
using JNPF.VisualDev;
|
||
using Microsoft.AspNetCore.Mvc;
|
||
using Microsoft.Extensions.Logging;
|
||
using Newtonsoft.Json;
|
||
using Npgsql;
|
||
using SqlSugar;
|
||
using Tnb.BasicData;
|
||
using Tnb.BasicData.Entities;
|
||
using Tnb.BasicData.Interfaces;
|
||
using Tnb.ProductionMgr.Entities.Entity;
|
||
using Tnb.ProductionMgr.Interfaces;
|
||
using Tnb.WarehouseMgr.Entities;
|
||
using Tnb.WarehouseMgr.Entities.Consts;
|
||
using Tnb.WarehouseMgr.Entities.Dto.Inputs;
|
||
using Tnb.WarehouseMgr.Entities.Entity;
|
||
using Tnb.WarehouseMgr.Entities.Enums;
|
||
using Tnb.WarehouseMgr.Interfaces;
|
||
|
||
namespace Tnb.WarehouseMgr
|
||
{
|
||
[OverideVisualDev(ModuleConsts.MODULE_WmsInventorycheck_ID)]
|
||
public class WmsInventorycheckService : BaseWareHouseService
|
||
{
|
||
private readonly ISqlSugarClient _db;
|
||
private readonly IDictionaryDataService _dictionaryDataService;
|
||
private readonly IUserManager _userManager;
|
||
private readonly IWareHouseService _wareHouseService;
|
||
private readonly IBillRullService _billRullService;
|
||
private readonly IPrdInstockService _prdInstockService;
|
||
private readonly IThirdApiRecordService _thirdApiRecordService;
|
||
private static Dictionary<string, object> _dicBillCodes = new();
|
||
public WmsInventorycheckService(
|
||
ISqlSugarRepository<WmsInventorycheckH> repository,
|
||
IDictionaryDataService dictionaryDataService,
|
||
IUserManager userManager,
|
||
IBillRullService billRullService,
|
||
IWareHouseService wareHouseService,
|
||
IPrdInstockService prdInstockService,
|
||
IThirdApiRecordService thirdApiRecordService,
|
||
IEventPublisher eventPublisher
|
||
)
|
||
{
|
||
_db = repository.AsSugarClient();
|
||
_dictionaryDataService = dictionaryDataService;
|
||
_userManager = userManager;
|
||
_billRullService = billRullService;
|
||
_wareHouseService = wareHouseService;
|
||
_thirdApiRecordService = thirdApiRecordService;
|
||
_prdInstockService = prdInstockService;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 盘点单提交
|
||
/// </summary>
|
||
/// <param name="input"></param>
|
||
/// <exception cref="ArgumentNullException"></exception>
|
||
[HttpPost]
|
||
public async Task<dynamic> Submit(WmsInventorycheckSubmitInput input)
|
||
{
|
||
try
|
||
{
|
||
|
||
|
||
return await ToApiResult(HttpStatusCode.OK, "成功");
|
||
}
|
||
catch (PostgresException ex)
|
||
{
|
||
Logger.LogError(ex.Message);
|
||
Logger.LogError(ex.StackTrace);
|
||
throw new AppFriendlyException($"{ex.Message}", 500);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Logger.LogInformation(ex.Message);
|
||
Logger.LogInformation(ex.StackTrace);
|
||
return await ToApiResult(HttpStatusCode.InternalServerError, ex.Message);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取仓库中该物料批次的所有库位库存信息
|
||
/// </summary>
|
||
/// <param name="input"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
public async Task<List<WmsInventoryCheckSearchOut>> MaterialLocationQty(WmsInventoryCheckQtyInput input)
|
||
{
|
||
if(string.IsNullOrEmpty(input.material_id))
|
||
throw Oops.Bah("物料id不能为空");
|
||
if (string.IsNullOrEmpty(input.warehouse_id))
|
||
throw Oops.Bah("仓库id不能为空");
|
||
if (string.IsNullOrEmpty(input.code_batch))
|
||
throw Oops.Bah("物料批次不能为空");
|
||
|
||
var result=new List<WmsInventoryCheckSearchOut>();
|
||
|
||
var items = await _db.Queryable<WmsCarryCode>().InnerJoin<WmsCarryH>((a, b) => a.carry_id == b.id)
|
||
.InnerJoin<BasLocation>((a, b, c) => b.location_id == c.id).InnerJoin<BasWarehouse>((a, b, c, d) => c.wh_id == d.id)
|
||
.LeftJoin<WmsTempCode>((a, b, c, d, e) => e.barcode == a.barcode)
|
||
.InnerJoin<BasMaterial>((a, b, c, d, e, f) => f.id == a.material_id)
|
||
.LeftJoin<DictionaryDataEntity>((a, b, c, d, e, f, g) => g.EnCode == f.unit_id && g.DictionaryTypeId == WmsWareHouseConst.UNITTYPEID)
|
||
.Where((a, b, c, d, e, f) => c.is_type == ((int)EnumLocationType.存储库位).ToString()
|
||
&& d.id == input.warehouse_id
|
||
&& a.material_id == input.material_id
|
||
&& a.code_batch==input.code_batch
|
||
)
|
||
.Select((a, b, c, d, e, f, g) => new WmsInventoryCheckSearchOut
|
||
{
|
||
material_code=a.material_code,
|
||
material_name = f.name,
|
||
material_id = f.id,
|
||
location_id = c.id,
|
||
location_code=c.location_code,
|
||
code_batch = a.code_batch,
|
||
material_specifition=f.material_specification,
|
||
material_standard=f.material_standard,
|
||
qty=0,
|
||
carry_id=a.carry_id,
|
||
carry_code=b.carry_code
|
||
}, true).ToListAsync();
|
||
|
||
List<WmsCarryCode> carryCodes = await _db.Queryable<WmsCarryCode>()
|
||
.InnerJoin<WmsCarryH>((a, b) => a.carry_id == b.id)
|
||
.InnerJoin<BasLocation>((a, b, c) => b.location_id == c.id).Where((a, b, c) => c.is_type == ((int)EnumLocationType.存储库位).ToString() && c.wh_id == input.warehouse_id && a.material_id == input.material_id && a.code_batch==input.code_batch).Select((a, b, c) => new WmsCarryCode
|
||
{
|
||
warehouse_id = c.wh_id
|
||
}, true).ToListAsync();
|
||
|
||
var storeMap = items.DistinctBy(x => new { x.material_id, x.location_id, x.code_batch }).ToDictionary(x => new { x.material_id, x.location_id, x.code_batch }, x => x);
|
||
|
||
var group = items.GroupBy(g => new { g.material_id, g.location_id, g.code_batch });
|
||
|
||
foreach (var itGroup in group)
|
||
{
|
||
_ = storeMap.TryGetValue(itGroup.Key, out WmsInventoryCheckSearchOut? stockReport);
|
||
|
||
List<WmsCarryCode> curCarryCodes = carryCodes.FindAll(x => x.material_id == itGroup.Key.material_id
|
||
&& x.location_id == itGroup.Key.location_id && x.code_batch == itGroup.Key.code_batch);
|
||
stockReport.qty = 0;
|
||
curCarryCodes.ForEach(x =>
|
||
{
|
||
stockReport.qty += x.codeqty;
|
||
});
|
||
result.Add(stockReport);
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 修改盘点的物料数量
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
public async Task<dynamic> SaveCheck(WmsInventoryCheckDSubmitInput input)
|
||
{
|
||
try
|
||
{
|
||
if (string.IsNullOrEmpty(input.checkd_bill_id))
|
||
throw Oops.Bah("盘点子表id不能为空");
|
||
|
||
await _db.Ado.BeginTranAsync();
|
||
var wmsInventoryCheckD = await _db.Queryable<WmsInventorycheckD>().Where(r => r.id == input.checkd_bill_id).FirstAsync();
|
||
if (wmsInventoryCheckD == null)
|
||
throw Oops.Bah($"盘点单子表id:{input.checkd_bill_id}数据不存在");
|
||
if (wmsInventoryCheckD.check_status == "1")
|
||
throw Oops.Bah($"该盘点单已完成盘点,不能重复盘点");
|
||
var wmsInventoryCheckH = await _db.Queryable<WmsInventorycheckH>().Where(r => r.id == wmsInventoryCheckD.bill_id).FirstAsync();
|
||
//汇总实际数量
|
||
decimal actual_qty = (input.details != null && input.details.Count > 0) ? input.details.Sum(r => (r.check_qty.HasValue ? r.check_qty.Value : 0)) : 0;
|
||
|
||
await _db.Updateable<WmsInventorycheckD>()
|
||
.SetColumns(r => r.actual_qty == actual_qty)
|
||
.SetColumns(r => r.check_time == DateTime.Now)
|
||
.SetColumns(r => r.checker_id == _userManager.UserId)
|
||
.SetColumns(r=>r.check_status=="1")
|
||
.Where(r => r.id == wmsInventoryCheckD.id).ExecuteCommandAsync();
|
||
//查找到盘点任务单下面所有的物料明细
|
||
var noChecks = await _db.Queryable<WmsInventorycheckD>().Where(r => r.bill_id == wmsInventoryCheckH.id).ToListAsync();
|
||
|
||
if(noChecks!=null && noChecks.Where(r=>r.check_status=="0" || string.IsNullOrEmpty(r.check_status)).Count()>0) //存在还没完成盘点的物料明细
|
||
{
|
||
await _db.Updateable<WmsInventorycheckH>()
|
||
.SetColumns(r => r.check_status == "1")
|
||
.Where(r => r.id == wmsInventoryCheckH.id).ExecuteCommandAsync();
|
||
}
|
||
else if(noChecks != null && noChecks.Where(r => r.check_status == "0" || string.IsNullOrEmpty(r.check_status)).Count() == 0) //盘点任务单下的物料明细都已盘点完成,任务单状态变成已盘点
|
||
{
|
||
await _db.Updateable<WmsInventorycheckH>()
|
||
.SetColumns(r => r.check_status == "2")
|
||
.SetColumns(r=>r.check_time==DateTime.Now)
|
||
.Where(r => r.id == wmsInventoryCheckH.id).ExecuteCommandAsync();
|
||
}
|
||
//先删除盘点记录表里面和此物料盘点明细有关的所有记录,再把此次盘点的详情保存到记录表
|
||
await _db.Deleteable<WmsInventorycheckRecord>().Where(r => r.bill_id == wmsInventoryCheckH.id && r.mat_bill_id == wmsInventoryCheckD.id).ExecuteCommandAsync();
|
||
if(input.details!=null && input.details.Count > 0)
|
||
{
|
||
var WmsInventorycheckRecords=new List<WmsInventorycheckRecord>();
|
||
|
||
foreach (var item in input.details)
|
||
{
|
||
var record = new WmsInventorycheckRecord()
|
||
{
|
||
create_id = _userManager.UserId,
|
||
create_time = DateTime.Now,
|
||
bill_id = wmsInventoryCheckH.id,
|
||
mat_bill_id = wmsInventoryCheckD.id,
|
||
carry_id = item.carry_id,
|
||
carry_code = item.carry_code,
|
||
location_id = item.location_id,
|
||
location_code = item.location_code,
|
||
code_batch = item.code_batch,
|
||
search_qty = item.qty.HasValue ? item.qty.Value.ToString() : "0",
|
||
check_qty = item.check_qty.HasValue ? item.check_qty.Value.ToString() : "0"
|
||
};
|
||
WmsInventorycheckRecords.Add(record);
|
||
}
|
||
await _db.Insertable(WmsInventorycheckRecords).ExecuteCommandAsync();
|
||
}
|
||
|
||
|
||
#region 调用bip接口
|
||
List<Dictionary<string, object>> requestData = new List<Dictionary<string, object>>();
|
||
List<string> tableIds = new List<string>();
|
||
tableIds.Add(wmsInventoryCheckD.material_id);
|
||
List<ErpExtendField> erpExtendFields = await _db.Queryable<ErpExtendField>().Where(x => tableIds.Contains(x.table_id)).ToListAsync();
|
||
Dictionary<string, object> erpRequestData = new Dictionary<string, object>();
|
||
|
||
erpRequestData.Add("cspecialhid", wmsInventoryCheckH.erp_pk);//盘点单主表id
|
||
List<Dictionary<string, object>> erpRequestDataDetails = new List<Dictionary<string, object>>();
|
||
erpRequestDataDetails.Add(new Dictionary<string, object>()
|
||
{
|
||
["cspecialbid"] = wmsInventoryCheckD.erp_line_pk, //盘点单子表id
|
||
["cspeciallid"] = wmsInventoryCheckH.erp_pk, //盘点单主表id
|
||
["crowno"] = wmsInventoryCheckD.lineno, //行号
|
||
["ncountnum"] = actual_qty, //实际盘点总数量
|
||
["cmaterialoid"] = erpExtendFields.Find(x => x.table_id == wmsInventoryCheckD.material_id)?.cmaterialoid ?? null, //物料id
|
||
});
|
||
erpRequestData.Add("dtls", erpRequestDataDetails);
|
||
requestData.Add(erpRequestData);
|
||
|
||
BasFactoryConfig config = await _db.Queryable<BasFactoryConfig>().FirstAsync(x => x.enabled == 1 && x.key == FactoryConfigConst.BIPURL);
|
||
|
||
ThirdWebapiRecord thirdWebapiRecord = new ThirdWebapiRecord();
|
||
thirdWebapiRecord.id = SnowflakeIdHelper.NextId();
|
||
thirdWebapiRecord.third_name = WmsWareHouseConst.BIP;
|
||
thirdWebapiRecord.name = "盘点单";
|
||
thirdWebapiRecord.method = "POST";
|
||
thirdWebapiRecord.url = config.value + "uapws/rest/InvCount/save";
|
||
//thirdWebapiRecord.url = WmsWareHouseConst.BIP_DOMAIN + "uapws/rest/InvCount/save";
|
||
thirdWebapiRecord.request_data = JsonConvert.SerializeObject(requestData);
|
||
thirdWebapiRecord.create_time = DateTime.Now;
|
||
thirdWebapiRecord.remark = "【WmsInventorycheckService SubmitCheck】盘点单主表id:" + wmsInventoryCheckH.id + ",盘点单子表id:" + wmsInventoryCheckD.id;
|
||
|
||
await _db.Insertable(thirdWebapiRecord).ExecuteCommandAsync();
|
||
|
||
BasFactoryConfig callErp = await _db.Queryable<BasFactoryConfig>().FirstAsync(x => x.enabled == 1 && x.key == FactoryConfigConst.CALLERP);
|
||
if (callErp.value == "1")
|
||
{
|
||
await _thirdApiRecordService.Send(new List<ThirdWebapiRecord> { thirdWebapiRecord }, "自动", _db);
|
||
}
|
||
|
||
#endregion
|
||
|
||
await _db.Ado.CommitTranAsync();
|
||
|
||
return await ToApiResult(HttpStatusCode.OK, "成功");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
await _db.Ado.RollbackTranAsync();
|
||
Logger.LogInformation(ex.Message);
|
||
Logger.LogInformation(ex.StackTrace);
|
||
return await ToApiResult(HttpStatusCode.InternalServerError, ex.Message);
|
||
}
|
||
}
|
||
|
||
|
||
}
|
||
}
|