shgx_tz_mom/ZR.Service/mes/wms/WmOneTimeInventoryService.cs
2024-11-18 20:14:00 +08:00

654 lines
26 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Linq;
using Infrastructure.Attribute;
using Infrastructure.Extensions;
using SqlSugar;
using ZR.Model;
using ZR.Model.MES.wms;
using ZR.Model.MES.wms.Dto;
using ZR.Repository;
using ZR.Service.mes.qc;
using ZR.Service.mes.wms.IService;
namespace ZR.Service.mes.wms
{
/// <summary>
/// 一次合格品仓库Service业务层处理
/// </summary>
[AppService(
ServiceType = typeof(IWmOneTimeInventoryService),
ServiceLifetime = LifeTime.Transient
)]
public class WmOneTimeInventoryService
: BaseService<WmOneTimeInventory>,
IWmOneTimeInventoryService
{
/// <summary>
/// 查询一次合格品仓库列表
/// </summary>
/// <param name="parm"></param>
/// <returns></returns>
public WmOneTimeInventoryTableDto GetList(WmOneTimeInventoryQueryDto parm)
{
var list = Context
.Queryable<WmMaterial>()
.LeftJoin<WmOneTimeInventory>((m, p) => m.Partnumber == p.Partnumber)
.Distinct()
.WhereIF(
!string.IsNullOrEmpty(parm.Description),
(m, p) => m.Description.Contains(parm.Description)
)
.WhereIF(
!string.IsNullOrEmpty(parm.Partnumber),
(m, p) => m.Partnumber.Contains(parm.Partnumber)
)
.Where((m, p) => m.Status == 1)
.Where((m, p) => m.Type == 1)
.WhereIF(parm.Status > -1, (m, p) => p.Status == parm.Status)
.WhereIF(parm.Type > 0, (m, p) => p.Type == parm.Type)
.OrderBy((m, p) => m.Description)
.Select(
(m, p) =>
new WmOneTimeInventoryDto
{
RealQuantity = 0,
Color = m.Color,
Specification = m.Specification,
Description = m.Description,
Id = p.Id,
BlankNum = p.BlankNum,
Partnumber = p.Partnumber,
Quantity = p.Quantity,
MaxNum = p.MaxNum,
MinNum = p.MinNum,
WarnNum = p.WarnNum,
Type = p.Type,
Status = p.Status,
Remark = p.Remark,
CreatedBy = p.CreatedBy,
CreatedTime = p.CreatedTime,
UpdatedBy = p.UpdatedBy,
UpdatedTime = p.UpdatedTime,
}
)
.ToList();
foreach (WmOneTimeInventoryDto item in list)
{
// 获取实际库存
List<string> partnumbers = new()
{
item.Partnumber
};
Dictionary<string, int> dict = GetBatchOneTimeRealPartNum(partnumbers);
item.RealQuantity = dict.TryGetValue(item.Partnumber, out int value) ? value : 0;
}
list = list.Where(it => it.RealQuantity != 0 || it.Quantity != 0)
.Where(it => !string.IsNullOrEmpty(it.Partnumber))
.DistinctBy(it => it.Partnumber)
.ToList();
int total = list.Count;
// 仓库总盘点零件数
int StocktakingTotal =
Context.Queryable<WmOneTimeInventory>().Sum(it => it.Quantity) ?? 0;
// 仓库当前查询盘点零件数
int QuantitySum = list.Sum(it => it.Quantity) ?? 0;
// 仓库当前查询实际零件数
int RealQuantitySum = list.Sum(it => it.RealQuantity);
WmOneTimeInventoryTableDto response = new()
{
Total = total,
StocktakingTotal = StocktakingTotal,
QuantitySum = QuantitySum,
RealQuantitySum = RealQuantitySum,
Result = list.Skip((parm.PageNum - 1) * parm.PageSize).Take(parm.PageSize).ToList(),
};
return response;
/*List<string> partnumberByDescription = new();
if (parm != null && !string.IsNullOrEmpty(parm.Description))
{
partnumberByDescription = Context
.Queryable<WmMaterial>()
.Where(it => it.Description.Contains(parm.Description))
.Select(it => it.Partnumber)
.ToList();
}
var predicate = Expressionable
.Create<WmOneTimeInventory>()
.AndIF(
!string.IsNullOrEmpty(parm.Description),
it => partnumberByDescription.Contains(it.Partnumber)
)
.AndIF(
!string.IsNullOrEmpty(parm.Partnumber),
it => it.Partnumber.Contains(parm.Partnumber)
)
.AndIF(parm.Status > -1, it => it.Status == parm.Status)
.AndIF(parm.Type > 0, it => it.Type == parm.Type);
var response = Queryable()
.Where(predicate.ToExpression())
.OrderByDescending(it => it.Quantity)
.ToPage<WmOneTimeInventory, WmOneTimeInventoryDto>(parm);
if (response.Result.Count > 0)
{
foreach (WmOneTimeInventoryDto item in response.Result)
{
WmMaterial material = Context
.Queryable<WmMaterial>()
.Where(it => it.Partnumber == item.Partnumber)
.Where(it => it.Type == 1)
.Where(it => it.Status == 1)
.First();
if (material == null)
{
item.Description = "此零件号不在物料清单内!";
continue;
}
item.Color = material.Color;
item.Specification = material.Specification;
item.Description = !string.IsNullOrEmpty(material.Description)
? material.Description
: material.ProductName;
// 获取实际库存
List<string> partnumbers = new List<string>();
partnumbers.Add(item.Partnumber);
Dictionary<string, int> dict = GetBatchOneTimeRealPartNum(partnumbers);
item.RealQuantity = dict.TryGetValue(item.Partnumber, out int value) ? value : 0;
}
}
return response;*/
}
/// <summary>
/// 获取详情
/// </summary>
/// <param name="Id"></param>
/// <returns></returns>
public WmOneTimeInventory GetInfo(string Id)
{
var response = Queryable().Where(x => x.Id == Id).First();
return response;
}
/// <summary>
/// 添加一次合格品仓库
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
public WmOneTimeInventory AddWmOneTimeInventory(WmOneTimeInventory model)
{
return Context.Insertable(model).ExecuteReturnEntity();
}
/// <summary>
/// 修改一次合格品仓库
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
public int UpdateWmOneTimeInventory(WmOneTimeInventory model)
{
return Update(model, true);
}
/// <summary>
/// 新增仓库操作记录
/// </summary>
/// <param name="fkInventoryId">抛光仓库主键</param>
/// <param name="code">同批功能识别编号</param>
/// <param name="partnumber">零件号</param>
/// <param name="type">类别</param>
/// <param name="changeQuantity">操作数字</param>
/// <param name="remark">备注</param>
/// <param name="createdBy">创建人</param>
/// <returns></returns>
public int AddOneTimeRecord(
string fkInventoryId,
string code,
string partnumber,
int type,
int? changeQuantity,
DateTime? actionTime,
string remark,
string createdBy
)
{
WmOneTimeRecord newOneTimeRecord =
new()
{
Id = SnowFlakeSingle.Instance.NextId().ToString(),
FkInventoryId = fkInventoryId,
Code = code,
Partnumber = partnumber,
BlankNum = "",
ChangeType = type,
ChangeQuantity = changeQuantity ?? 0,
ActionTime = actionTime,
Status = 1,
Remark = remark,
CreatedBy = createdBy,
CreatedTime = DateTime.Now.ToLocalTime(),
UpdatedBy = createdBy,
UpdatedTime = DateTime.Now.ToLocalTime(),
};
return Context.Insertable(newOneTimeRecord).ExecuteCommand();
}
public int DoWmOneTimeWarehousing(WmOneTimeInventory parm)
{
try
{
Context.Ado.BeginTran();
// 零件号检查
string partnumber = parm.Partnumber;
// 检查是否存在库中
WmOneTimeInventory oneTimeInventory = Context
.Queryable<WmOneTimeInventory>()
.Where(it => it.Partnumber == partnumber)
.Where(it => it.Type == parm.Type)
.Where(it => it.Status == 1)
.First();
if (oneTimeInventory == null)
{
// 为空则新增库
WmOneTimeInventory newWmOneTimeInventory =
new()
{
Id = SnowFlakeSingle.Instance.NextId().ToString(),
BlankNum = "",
Partnumber = partnumber,
Type = parm.Type,
Quantity = parm.Quantity,
MaxNum = 0,
MinNum = 0,
WarnNum = 0,
Status = 1,
Remark = "系统自动创建库",
CreatedBy = parm.CreatedBy,
CreatedTime = DateTime.Now.ToLocalTime(),
UpdatedBy = parm.CreatedBy,
UpdatedTime = DateTime.Now.ToLocalTime(),
};
WmOneTimeInventory addWmOneTimeInventory = Context
.Insertable(newWmOneTimeInventory)
.ExecuteReturnEntity();
string code = !string.IsNullOrEmpty(parm.WorkOrder)
? parm.WorkOrder
: SnowFlakeSingle.Instance.NextId().ToString();
string remark = "初次创建仓库,新增入库数据 " + parm.Remark;
int successNum = AddOneTimeRecord(
addWmOneTimeInventory.Id,
code,
partnumber,
1,
parm.Quantity,
parm.ActionTime,
remark,
parm.CreatedBy
);
if (successNum == 0)
{
Context.Ado.RollbackTran();
throw new Exception("入库日志添加失败");
}
}
else
{
oneTimeInventory.Quantity += parm.Quantity;
int updateNum = Context.Updateable(oneTimeInventory).ExecuteCommand();
if (updateNum == 0)
{
Context.Ado.RollbackTran();
throw new Exception("修改一次合格仓库数据失败");
}
// 已有则新增记录
string code = !string.IsNullOrEmpty(parm.WorkOrder)
? parm.WorkOrder
: SnowFlakeSingle.Instance.NextId().ToString();
int successNum = AddOneTimeRecord(
oneTimeInventory.Id,
code,
partnumber,
1,
parm.Quantity,
parm.ActionTime,
parm.Remark,
parm.CreatedBy
);
if (successNum == 0)
{
Context.Ado.RollbackTran();
throw new Exception("入库日志添加失败");
}
}
Context.Ado.CommitTran();
return 1;
}
catch (Exception e)
{
Context.Ado.RollbackTran();
throw new Exception(e.Message);
}
}
public int DoWmOneTimeRetrieval(WmOneTimeInventory parm)
{
try
{
Context.Ado.BeginTran();
// 零件号检查
string partnumber = parm.Partnumber;
// 检查是否存在库中
WmOneTimeInventory oneTimeInventory = Context
.Queryable<WmOneTimeInventory>()
.Where(it => it.Partnumber == partnumber)
.Where(it => it.Type == parm.Type)
.Where(it => it.Status == 1)
.First();
if (oneTimeInventory == null)
{
// 为空则新增库
WmOneTimeInventory newWmOneTimeInventory =
new()
{
Id = SnowFlakeSingle.Instance.NextId().ToString(),
BlankNum = "",
Partnumber = partnumber,
Type = parm.Type,
Quantity = parm.Quantity * -1,
MaxNum = 0,
MinNum = 0,
WarnNum = 0,
Status = 1,
Remark = "系统自动创建库",
CreatedBy = parm.CreatedBy,
CreatedTime = DateTime.Now.ToLocalTime(),
UpdatedBy = parm.CreatedBy,
UpdatedTime = DateTime.Now.ToLocalTime(),
};
WmOneTimeInventory addWmOneTimeInventory = Context
.Insertable(newWmOneTimeInventory)
.ExecuteReturnEntity();
string code = !string.IsNullOrEmpty(parm.WorkOrder)
? parm.WorkOrder
: SnowFlakeSingle.Instance.NextId().ToString();
string remark = "初次创建仓库,新增手动出库数据" + parm.Remark;
int successNum = AddOneTimeRecord(
addWmOneTimeInventory.Id,
code,
partnumber,
2,
parm.Quantity,
parm.ActionTime,
remark,
parm.CreatedBy
);
if (successNum == 0)
{
Context.Ado.RollbackTran();
throw new Exception("出库日志添加失败");
}
}
else
{
oneTimeInventory.Quantity -= parm.Quantity;
int updateNum = Context.Updateable(oneTimeInventory).ExecuteCommand();
if (updateNum == 0)
{
Context.Ado.RollbackTran();
throw new Exception("修改一次合格仓库零件数失败");
}
// 已有则新增记录
string code = !string.IsNullOrEmpty(parm.WorkOrder)
? parm.WorkOrder
: SnowFlakeSingle.Instance.NextId().ToString();
int successNum = AddOneTimeRecord(
oneTimeInventory.Id,
code,
partnumber,
2,
parm.Quantity,
parm.ActionTime,
parm.Remark,
parm.CreatedBy
);
if (successNum == 0)
{
Context.Ado.RollbackTran();
throw new Exception("出库日志添加失败");
}
}
Context.Ado.CommitTran();
return 1;
}
catch (Exception e)
{
Context.Ado.RollbackTran();
throw new Exception(e.Message);
}
}
public int DoWmOneTimeStocktaking(WmOneTimeInventory parm)
{
if (parm.Quantity < 0)
{
throw new Exception("修改的零件数小于0");
}
try
{
Context.Ado.BeginTran();
// 检查是否存在库中
WmOneTimeInventory oneTImeInventory = Context
.Queryable<WmOneTimeInventory>()
.Where(it => it.Id == parm.Id)
.Where(it => it.Status == 1)
.First();
if (oneTImeInventory == null)
{
Context.Ado.RollbackTran();
throw new Exception("盘点记录不存在" + parm.Id);
}
Context.Updateable(parm).IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommand();
// 已有则新增记录
string code = !string.IsNullOrEmpty(parm.WorkOrder)
? parm.WorkOrder
: SnowFlakeSingle.Instance.NextId().ToString();
int successNum = AddOneTimeRecord(
parm.Id,
code,
parm.Partnumber,
3,
parm.Quantity,
parm.ActionTime,
parm.Remark,
parm.CreatedBy
);
if (successNum == 0)
{
Context.Ado.RollbackTran();
throw new Exception("盘点日志添加失败");
}
Context.Ado.CommitTran();
return successNum;
}
catch (Exception e)
{
Context.Ado.RollbackTran();
throw new Exception(e.Message);
}
}
// 获取仓库零件数量
public int GetPartNumber()
{
return Context
.Queryable<WmOneTimeInventory>()
.Where(it => it.Status == 1)
.Sum(it => it.Quantity) ?? 0;
}
// Util 获取物料清单,不包含毛坯
public List<WmMaterial> GetWmMaterialList(string partnumber)
{
// 获取物料信息
return Context
.Queryable<WmMaterial>()
.WhereIF(
!string.IsNullOrEmpty(partnumber),
it => it.Partnumber.Contains(partnumber)
)
.Where(it => !string.IsNullOrEmpty(it.Partnumber))
.Where(it => it.Type == 1)
.Where(it => it.Status == 1)
.Distinct()
.OrderBy(it => it.Description)
.ToList();
}
public List<WmOneTimeInventoryExportDto> GetExportList(WmOneTimeInventoryQueryDto parm)
{
try
{
List<WmMaterial> materials = GetWmMaterialList(parm.Partnumber);
// 获取所有partnumber列表
List<string> partnumbers = materials
.Where(it => !string.IsNullOrEmpty(it.Partnumber))
.Select(it => it.Partnumber)
.Distinct()
.ToList();
// 批量获取盘点数和现有库存
Dictionary<string, object> stockNumbers = GetBatchOneTimeStockPartNum(partnumbers);
Dictionary<string, int> realNumbers = GetBatchOneTimeRealPartNum(partnumbers);
// 更新盘点时间
DateTime dateTime = DateTime.Now.ToLocalTime();
// 构建导出数据
List<WmOneTimeInventoryExportDto> exportDto = materials
.Select(it =>
{
bool found1 = stockNumbers.TryGetValue(it.Partnumber, out object value1);
int stockNumber = found1 && value1 != null ? Convert.ToInt32(value1) : 0;
bool found2 = realNumbers.TryGetValue(it.Partnumber, out int realNumber);
return new WmOneTimeInventoryExportDto
{
= it.Partnumber,
= it.Color,
= it.Specification,
= it.Description,
= stockNumber,
= found2 ? realNumber : 0,
= dateTime,
};
})
.ToList();
return exportDto;
}
catch (Exception e)
{
throw;
}
}
// Util 获取指定抛光库零件盘点库存
public Dictionary<string, object> GetBatchOneTimeStockPartNum(List<string> partnumbers)
{
return Context
.Queryable<WmOneTimeInventory>()
.Where(it => partnumbers.Contains(it.Partnumber))
.GroupBy(it => it.Partnumber)
.ToDictionary(g => g.Partnumber, g => SqlFunc.AggregateSum(g.Quantity) ?? 0);
}
// Util 获取指定一次合格库零件加报表后库存
public Dictionary<string, int> GetBatchOneTimeRealPartNum(List<string> partnumbers)
{
try
{
// 盘点时间
DateTime? checkTime =
Context
.Queryable<WmOneTimeInventory>()
.Where(it => it.Status == 1)
.Select(it => it.CreatedTime)
.First() ?? new DateTime(2024, 10, 19, 0, 0, 0);
// DateTime
CommonFQCService commonFQCService = new();
// 获取报表数据
// 一次合格计算后库存 = 盘点库存 + 产线合格 + 抛光合格 - gp12投入 - 后道直接出库
return commonFQCService.GetBatchOneTimePartRealStock(partnumbers, checkTime.Value);
}
catch (Exception e)
{
throw;
}
}
/// <summary>
/// 导入数据
/// </summary>
/// <param name="importData"></param>
/// <returns></returns>
public (string, object, object) ImportExcel(List<WmOneTimeInventoryExportDto> importList)
{
List<WmOneTimeInventory> wmOneTimeInventorylist = importList
.Select(it => new WmOneTimeInventory
{
Id = SnowFlakeSingle.Instance.NextId().ToString(),
Type = 1,
Status = 1,
MaxNum = 0,
MinNum = 0,
WarnNum = 0,
CreatedBy = "页面导入",
Remark = "EXCEL 盘点导入",
CreatedTime = it. ?? DateTime.Now.ToLocalTime(),
Partnumber = it.,
Quantity = it.
})
.ToList();
var x = Context
.Storageable(wmOneTimeInventorylist)
.SplitError(x => x.Item.Partnumber.IsEmpty(), "零件号不能为空")
.SplitError(x => x.Item.Quantity.IsEmpty(), "盘点数不能为空")
.SplitUpdate(it => it.Any()) // 数据库存在更新
.SplitDelete(it => it.Item.Quantity == 0) //盘点数为0的不导入
.SplitInsert(it => true) // 其余插入
.WhereColumns(it => it.Partnumber) //如果不是主键可以这样实现多字段it=>new{it.x1,it.x2}
.ToStorage();
// 清空全部
var result = x.AsInsertable.ExecuteCommand(); //不存在则插入;
var result2 = x.AsUpdateable.IgnoreColumns(it => new { it.Id }).ExecuteCommand(); //存在则修改;
var result3 = x.AsDeleteable.ExecuteCommand(); //盘点数为0的删除;
string msg = string.Format(
" 插入{0} 更新{1} 错误数据{2} 不计算数据{3} 删除数据{4} 总共{5}",
x.InsertList.Count,
x.UpdateList.Count,
x.ErrorList.Count,
x.IgnoreList.Count,
x.DeleteList.Count,
x.TotalList.Count
);
//输出统计
Console.WriteLine(msg);
//输出错误信息
foreach (var item in x.ErrorList)
{
Console.WriteLine("零件异常:" + item.Item.Partnumber + " : " + item.StorageMessage);
}
return (msg, x.ErrorList, x.IgnoreList);
}
}
}