Files
kunshan-bzfm-mes-backend/DOAN.Service/MES/Material/MmInventoryService.cs

426 lines
16 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 DOAN.Model.BZFM;
using DOAN.Model.BZFM.Dto;
using DOAN.Model.Mobile.Dto;
using DOAN.Repository;
using DOAN.Service.BZFM.IBZFMService;
using Infrastructure.Attribute;
using Infrastructure.Extensions;
namespace DOAN.Service.BZFM
{
/// <summary>
/// 库存表Service业务层处理
/// </summary>
[AppService(ServiceType = typeof(IMmInventoryService), ServiceLifetime = LifeTime.Transient)]
public class MmInventoryService : BaseService<MmInventory>, IMmInventoryService
{
/// <summary>
/// 查询库存表列表
/// </summary>
/// <param name="parm"></param>
/// <returns></returns>
public PagedInfo<MmInventoryDto> GetList(MmInventoryQueryDto parm)
{
var predicate = QueryExp(parm);
var response = Queryable()
.Where(predicate.ToExpression())
.ToPage<MmInventory, MmInventoryDto>(parm);
return response;
}
/// <summary>
/// 获取详情
/// </summary>
/// <param name="Id"></param>
/// <returns></returns>
public MmInventory GetInfo(int Id)
{
var response = Queryable().Where(x => x.Id == Id).First();
return response;
}
/// <summary>
/// 添加库存表
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
public MmInventory AddMmInventory(MmInventory model)
{
return Insertable(model).ExecuteReturnEntity();
}
/// <summary>
/// 修改库存表
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
public int UpdateMmInventory(MmInventory model)
{
return Update(model, true);
}
/// <summary>
/// 查询导出表达式
/// </summary>
/// <param name="parm"></param>
/// <returns></returns>
private static Expressionable<MmInventory> QueryExp(MmInventoryQueryDto parm)
{
var predicate = Expressionable
.Create<MmInventory>()
.AndIF(
!string.IsNullOrEmpty(parm.MaterialCode),
m => m.MaterialCode.Contains(parm.MaterialCode)
)
.AndIF(
!string.IsNullOrEmpty(parm.WarehouseName),
m => m.WarehouseName.Contains(parm.WarehouseName)
)
.AndIF(
!string.IsNullOrEmpty(parm.WarehouseCode),
m => m.WarehouseCode.Contains(parm.WarehouseCode)
)
.AndIF(
!string.IsNullOrEmpty(parm.LocationCode),
m => m.LocationCode.Contains(parm.LocationCode)
)
.AndIF(!string.IsNullOrEmpty(parm.BatchNo), m => m.BatchNo.Contains(parm.BatchNo));
return predicate;
}
public List<MmMaterialOption> GetMaterialOption()
{
try
{
return Context
.Queryable<MmMaterial>()
.Where(it => it.Status == "启用")
.Select(it => new MmMaterialOption
{
MaterialCode = it.MaterialCode,
MaterialName = it.MaterialName,
CategoryCode = it.CategoryCode,
Specification = it.Specification,
})
.ToList();
}
catch (Exception)
{
throw;
}
}
public List<MmLocationOption> GetLocationOption()
{
try
{
return Context
.Queryable<MmLocation>()
.Where(it => it.Status == "启用")
.Select(it => new MmLocationOption
{
WarehouseCode = it.WarehouseCode,
WarehouseName = it.WarehouseName,
LocationCode = it.LocationCode,
LocationName = it.LocationName,
LocationType = it.LocationType,
})
.ToList();
}
catch (Exception)
{
throw;
}
}
public List<MmTransactionOption> GetTransactionOption()
{
try
{
return Context
.Queryable<MmTransactionType>()
.Where(it => it.Status == "启用")
.Select(it => new MmTransactionOption
{
Label = it.TypeName,
Value = it.TypeCode,
})
.ToList();
}
catch (Exception)
{
throw;
}
}
public string CreateInboundReceipt(InboundReceiptDto parm)
{
try
{
DateTime nowDate = DateTime.Now;
// 计算有符号变动量(蓝单为正,红单为负)
decimal delta = GetSignedQuantity(parm.ReceiptType, parm.Quantity);
// 校验物料和库位
var mmMaterial = Context
.Queryable<MmMaterial>()
.Where(it => it.MaterialCode == parm.MaterialCode)
.First();
if (mmMaterial == null)
return "物料不存在!";
var mmLocation = Context
.Queryable<MmLocation>()
.Where(it => it.WarehouseCode == parm.WarehouseCode)
.Where(it => it.LocationCode == parm.LocationCode)
.First();
if (mmLocation == null)
return "仓库编码或库位编码不存在!";
// 启用事务
Context.Ado.BeginTran();
// 获取现有库存(同物料、批次、库位)
var mmInventory = Context
.Queryable<MmInventory>()
.Where(it => it.MaterialCode == parm.MaterialCode)
.Where(it => it.BatchNo == parm.BatchNo)
.Where(it => it.WarehouseCode == parm.WarehouseCode)
.Where(it => it.LocationCode == parm.LocationCode)
.First();
// 若不存在则新增;存在则更新
if (mmInventory == null)
{
var newInventory = new MmInventory()
{
MaterialCode = mmMaterial.MaterialCode,
MaterialName = mmMaterial.MaterialName,
LocationCode = mmLocation.LocationCode,
LocationName = mmLocation.LocationName,
WarehouseCode = mmLocation.WarehouseCode,
WarehouseName = mmLocation.WarehouseName,
BatchNo = parm.BatchNo,
CurrentQty = delta,
Unit = parm.Unit,
ExpiryDate = parm.ExpiryDate,
LastUpdatedTime = null,
ProductionDate = parm.ProductionDate,
CreatedTime = nowDate,
};
Context.Insertable(newInventory).ExecuteCommand();
}
else
{
Context
.Updateable(mmInventory)
.SetColumns(it => it.CurrentQty == it.CurrentQty + delta)
.ExecuteCommand();
}
// 插入入库记录,入库单号使用自动增长策略(同日期按序号)
var inboundNo = GenerateReceiptNo("RK");
MmRecordInbound newRecord = new()
{
InboundNo = inboundNo,
BatchNo = parm.BatchNo,
Operator = parm.Operator,
MaterialCode = mmMaterial.MaterialCode,
MaterialName = mmMaterial.MaterialName,
LocationCode = mmLocation.LocationCode,
LocationName = mmLocation.LocationName,
WarehouseCode = mmLocation.WarehouseCode,
WarehouseName = mmLocation.WarehouseName,
Quantity = parm.Quantity,
Unit = parm.Unit,
SupplierCode = parm.SupplierCode,
SupplierName = parm.SupplierName,
ProductionDate = parm.ProductionDate,
ExpiryDate = parm.ExpiryDate,
CreatedTime = nowDate,
TransactionType = parm.TransactionType,
Remarks = parm.Remarks,
};
Context.Insertable(newRecord).ExecuteCommand();
Context.Ado.CommitTran();
return "ok";
}
catch (Exception ex)
{
// 回滚操作
Context.Ado.RollbackTran();
return ex.Message;
}
}
public string CreateOutboundReceipt(OutboundReceiptDto parm)
{
try
{
DateTime nowDate = DateTime.Now;
// 计算有符号变动量(蓝单为正,红单为负)
decimal delta = GetSignedQuantity(parm.ReceiptType, parm.Quantity);
var mmMaterial = Context
.Queryable<MmMaterial>()
.Where(it => it.MaterialCode == parm.MaterialCode)
.First();
if (mmMaterial == null)
return "物料不存在!";
var mmLocation = Context
.Queryable<MmLocation>()
.Where(it => it.WarehouseCode == parm.WarehouseCode)
.Where(it => it.LocationCode == parm.LocationCode)
.First();
if (mmLocation == null)
return "仓库编码或库位编码不存在!";
Context.Ado.BeginTran();
var mmInventory = Context
.Queryable<MmInventory>()
.Where(it => it.MaterialCode == parm.MaterialCode)
.Where(it => it.BatchNo == parm.BatchNo)
.Where(it => it.WarehouseCode == parm.WarehouseCode)
.Where(it => it.LocationCode == parm.LocationCode)
.First();
if (mmInventory == null)
{
var newInventory = new MmInventory()
{
MaterialCode = mmMaterial.MaterialCode,
MaterialName = mmMaterial.MaterialName,
LocationCode = mmLocation.LocationCode,
LocationName = mmLocation.LocationName,
WarehouseCode = mmLocation.WarehouseCode,
WarehouseName = mmLocation.WarehouseName,
BatchNo = parm.BatchNo,
CurrentQty = -delta,
Unit = parm.Unit,
LastUpdatedTime = null,
CreatedTime = nowDate,
};
Context.Insertable(newInventory).ExecuteCommand();
}
else
{
if (mmInventory.CurrentQty - delta < 0)
{
Context.Ado.RollbackTran();
return "库存不足,无法出库";
}
Context
.Updateable(mmInventory)
.SetColumns(it => it.CurrentQty == it.CurrentQty - delta)
.ExecuteCommand();
}
var outboundNo = GenerateReceiptNo("CK");
MmRecordOutbound newRecord = new()
{
OutboundNo = outboundNo,
BatchNo = parm.BatchNo,
Operator = parm.Operator,
MaterialCode = mmMaterial.MaterialCode,
MaterialName = mmMaterial.MaterialName,
LocationCode = mmLocation.LocationCode,
LocationName = mmLocation.LocationName,
WarehouseCode = mmLocation.WarehouseCode,
WarehouseName = mmLocation.WarehouseName,
Quantity = parm.Quantity,
Unit = parm.Unit,
CreatedTime = nowDate,
TransactionType = parm.TransactionType,
Remarks = parm.Remarks,
};
Context.Insertable(newRecord).ExecuteCommand();
Context.Ado.CommitTran();
return "ok";
}
catch (Exception ex)
{
// 回滚操作
Context.Ado.RollbackTran();
return ex.Message;
}
}
/// <summary>
/// 根据单据类型与数量计算有符号变动量(蓝单为正,红单为负)
/// </summary>
/// <param name="receiptType">1 表示蓝单(正),其它为红单(负)</param>
/// <param name="quantity">1 表示蓝单(正),其它为红单(负)</param>
private static decimal GetSignedQuantity(int receiptType, decimal quantity)
{
return receiptType == 1 ? Math.Abs(quantity) : -Math.Abs(quantity);
}
/// <summary>
/// 生成单据编号,格式:{prefix}{yyyyMMdd}-{nnn}
/// 例如RK20251225-001
/// </summary>
private string GenerateReceiptNo(string prefix)
{
var datePart = DateTime.Now.ToString("yyyyMMdd");
var baseNo = prefix + datePart + "-";
// 尝试从入库/出库表中获取当天最大的编号后缀
try
{
if (prefix == "RK")
{
var last = Context
.Queryable<MmRecordInbound>()
.Where(it => it.InboundNo.StartsWith(prefix + datePart))
.OrderBy(it => it.InboundNo + " desc")
.Select(it => it.InboundNo)
.First();
if (string.IsNullOrEmpty(last))
{
return baseNo + "001";
}
var suf = last.Substring((prefix + datePart).Length).TrimStart('-', '_');
if (int.TryParse(suf, out var n))
{
return baseNo + (n + 1).ToString("D3");
}
return baseNo + "001";
}
else
{
var last = Context
.Queryable<MmRecordOutbound>()
.Where(it => it.OutboundNo.StartsWith(prefix + datePart))
.OrderBy(it => it.OutboundNo + " desc")
.Select(it => it.OutboundNo)
.First();
if (string.IsNullOrEmpty(last))
{
return baseNo + "001";
}
var suf = last.Substring((prefix + datePart).Length).TrimStart('-', '_');
if (int.TryParse(suf, out var n))
{
return baseNo + (n + 1).ToString("D3");
}
return baseNo + "001";
}
}
catch
{
return baseNo + "001";
}
}
}
}