1213 lines
50 KiB
C#
1213 lines
50 KiB
C#
using DOAN.Model;
|
||
using DOAN.Model.BZFM;
|
||
using DOAN.Model.BZFM.Dto;
|
||
using DOAN.Model.MES.order;
|
||
using DOAN.Model.MES.product;
|
||
using DOAN.Repository;
|
||
using DOAN.Service.BZFM.IBZFMService;
|
||
using Infrastructure.Attribute;
|
||
using Infrastructure.Converter;
|
||
using Infrastructure.Extensions;
|
||
using Microsoft.AspNetCore.Http;
|
||
using Microsoft.IdentityModel.Tokens;
|
||
using NPOI.SS.UserModel;
|
||
using NPOI.XSSF.UserModel;
|
||
|
||
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 == parm.MaterialCode
|
||
)
|
||
.AndIF(
|
||
!string.IsNullOrEmpty(parm.SupplierCode),
|
||
m => m.SupplierCode == parm.SupplierCode
|
||
)
|
||
.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.SupplierName),
|
||
m => m.SupplierName.Contains(parm.SupplierName)
|
||
)
|
||
.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
|
||
{
|
||
Id = it.Id,
|
||
MaterialCode = it.MaterialCode,
|
||
MaterialName = it.MaterialName,
|
||
CategoryCode = it.CategoryCode,
|
||
Specification = it.Specification,
|
||
SupplierCode = it.SupplierCode,
|
||
SupplierName = it.SupplierName,
|
||
Type = it.Type,
|
||
})
|
||
.OrderBy(it => it.Type)
|
||
.ToList();
|
||
}
|
||
catch (Exception)
|
||
{
|
||
throw;
|
||
}
|
||
}
|
||
|
||
public List<MmLocationOption> GetLocationOption()
|
||
{
|
||
try
|
||
{
|
||
return Context
|
||
.Queryable<MmLocation>()
|
||
.Where(it => it.Status == "启用")
|
||
.Select(it => new MmLocationOption
|
||
{
|
||
Id = it.Id,
|
||
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)
|
||
.WhereIF(
|
||
!string.IsNullOrEmpty(parm.SupplierCode),
|
||
it => it.SupplierCode == parm.SupplierCode
|
||
)
|
||
.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,
|
||
SupplierCode = mmMaterial.SupplierCode,
|
||
SupplierName = mmMaterial.SupplierName,
|
||
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
|
||
{
|
||
mmInventory.CurrentQty += delta;
|
||
Context
|
||
.Updateable(mmInventory)
|
||
.UpdateColumns(it => it.CurrentQty)
|
||
.ExecuteCommand();
|
||
}
|
||
|
||
// 插入入库记录,入库单号使用自动增长策略(同日期按序号)
|
||
var inboundNo = GenerateReceiptNo("RK");
|
||
MmRecordInbound newRecord = new()
|
||
{
|
||
InboundNo = inboundNo,
|
||
BatchNo = parm.BatchNo,
|
||
Operator = parm.Operator,
|
||
StoveCode = parm.StoveCode,
|
||
MaterialCode = mmMaterial.MaterialCode,
|
||
MaterialName = mmMaterial.MaterialName,
|
||
SupplierCode = mmMaterial.SupplierCode,
|
||
SupplierName = mmMaterial.SupplierName,
|
||
LocationCode = mmLocation.LocationCode,
|
||
LocationName = mmLocation.LocationName,
|
||
WarehouseCode = mmLocation.WarehouseCode,
|
||
WarehouseName = mmLocation.WarehouseName,
|
||
//TODO 待调整(可能涉及记录汇总)
|
||
Quantity = delta,
|
||
Unit = parm.Unit,
|
||
ProductionDate = parm.ProductionDate,
|
||
Workorder = parm.Workorder,
|
||
WorkorderRaw = parm.WorkorderRaw,
|
||
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);
|
||
|
||
Context.Ado.BeginTran();
|
||
MmInventory mmInventory = null;
|
||
if (parm.InventoryId == -1)
|
||
{
|
||
var mmMaterial = Context
|
||
.Queryable<MmMaterial>()
|
||
.Where(it => it.MaterialCode == parm.MaterialCode)
|
||
.WhereIF(
|
||
!string.IsNullOrEmpty(parm.SupplierCode),
|
||
it => it.SupplierCode == parm.SupplierCode
|
||
)
|
||
.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 "仓库编码或库位编码不存在!";
|
||
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)
|
||
{
|
||
if (parm.ReceiptType == 1)
|
||
{
|
||
//库存为0或者不存在,不允许出库
|
||
Context.Ado.RollbackTran();
|
||
return "库存不存在,禁止出库!";
|
||
}
|
||
var newInventory = new MmInventory()
|
||
{
|
||
MaterialCode = mmMaterial.MaterialCode,
|
||
MaterialName = mmMaterial.MaterialName,
|
||
SupplierCode = mmMaterial.SupplierCode,
|
||
SupplierName = mmMaterial.SupplierName,
|
||
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();
|
||
mmInventory = newInventory;
|
||
}
|
||
else
|
||
{
|
||
if (mmInventory.CurrentQty - delta < 0)
|
||
{
|
||
Context.Ado.RollbackTran();
|
||
return "库存不足,无法出库!";
|
||
}
|
||
mmInventory.CurrentQty -= delta;
|
||
Context
|
||
.Updateable(mmInventory)
|
||
.UpdateColumns(it => it.CurrentQty)
|
||
.ExecuteCommand();
|
||
}
|
||
|
||
var outboundNo = GenerateReceiptNo("CK");
|
||
MmRecordOutbound newRecord = new()
|
||
{
|
||
OutboundNo = outboundNo,
|
||
BatchNo = parm.BatchNo,
|
||
Operator = parm.Operator,
|
||
MaterialCode = mmMaterial.MaterialCode,
|
||
MaterialName = mmMaterial.MaterialName,
|
||
SupplierCode = mmMaterial.SupplierCode,
|
||
SupplierName = mmMaterial.SupplierName,
|
||
LocationCode = mmLocation.LocationCode,
|
||
LocationName = mmLocation.LocationName,
|
||
WarehouseCode = mmLocation.WarehouseCode,
|
||
WarehouseName = mmLocation.WarehouseName,
|
||
|
||
//TODO 待调整(可能涉及记录汇总)
|
||
Quantity = -delta,
|
||
Unit = parm.Unit,
|
||
CreatedTime = nowDate,
|
||
TransactionType = parm.TransactionType,
|
||
Workorder = parm.Workorder,
|
||
WorkorderRaw = parm.WorkorderRaw,
|
||
OrderNo = parm.OrderNo,
|
||
Remarks = parm.Remarks,
|
||
};
|
||
Context.Insertable(newRecord).ExecuteCommand();
|
||
Context.Ado.CommitTran();
|
||
return "ok";
|
||
|
||
}
|
||
else
|
||
{
|
||
mmInventory = Context
|
||
.Queryable<MmInventory>()
|
||
.Where(it => it.Id == parm.InventoryId)
|
||
.First();
|
||
if (mmInventory == null)
|
||
{
|
||
if (parm.ReceiptType == 1)
|
||
{
|
||
//库存为0或者不存在,不允许出库
|
||
Context.Ado.RollbackTran();
|
||
return "库存不存在,禁止出库!";
|
||
}
|
||
var newInventory = new MmInventory()
|
||
{
|
||
MaterialCode = mmInventory.MaterialCode,
|
||
MaterialName = mmInventory.MaterialName,
|
||
SupplierCode = mmInventory.SupplierCode,
|
||
SupplierName = mmInventory.SupplierName,
|
||
LocationCode = mmInventory.LocationCode,
|
||
LocationName = mmInventory.LocationName,
|
||
WarehouseCode = mmInventory.WarehouseCode,
|
||
WarehouseName = mmInventory.WarehouseName,
|
||
BatchNo = parm.BatchNo,
|
||
CurrentQty = -delta,
|
||
Unit = parm.Unit,
|
||
LastUpdatedTime = null,
|
||
CreatedTime = nowDate,
|
||
};
|
||
Context.Insertable(newInventory).ExecuteCommand();
|
||
mmInventory = newInventory;
|
||
}
|
||
else
|
||
{
|
||
if (mmInventory.CurrentQty - delta < 0)
|
||
{
|
||
Context.Ado.RollbackTran();
|
||
return "库存不足,无法出库!";
|
||
}
|
||
mmInventory.CurrentQty -= delta;
|
||
Context
|
||
.Updateable(mmInventory)
|
||
.UpdateColumns(it => it.CurrentQty)
|
||
.ExecuteCommand();
|
||
}
|
||
|
||
var outboundNo = GenerateReceiptNo("CK");
|
||
MmRecordOutbound newRecord = new()
|
||
{
|
||
OutboundNo = outboundNo,
|
||
BatchNo = parm.BatchNo,
|
||
Operator = parm.Operator,
|
||
MaterialCode = mmInventory.MaterialCode,
|
||
MaterialName = mmInventory.MaterialName,
|
||
SupplierCode = mmInventory.SupplierCode,
|
||
SupplierName = mmInventory.SupplierName,
|
||
LocationCode = mmInventory.LocationCode,
|
||
LocationName = mmInventory.LocationName,
|
||
WarehouseCode = mmInventory.WarehouseCode,
|
||
WarehouseName = mmInventory.WarehouseName,
|
||
|
||
//TODO 待调整(可能涉及记录汇总)
|
||
Quantity = -delta,
|
||
Unit = parm.Unit,
|
||
CreatedTime = nowDate,
|
||
TransactionType = parm.TransactionType,
|
||
Workorder = parm.Workorder,
|
||
WorkorderRaw = parm.WorkorderRaw,
|
||
OrderNo = parm.OrderNo,
|
||
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))
|
||
.OrderByDescending(it => it.InboundNo)
|
||
.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))
|
||
.OrderByDescending(it => it.OutboundNo)
|
||
.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";
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 导入数据
|
||
/// </summary>
|
||
/// <param name="formFile"></param>
|
||
/// <returns></returns>
|
||
public ImportResultDto ImportInventory(IFormFile formFile, string username)
|
||
{
|
||
string message = "导入成功";
|
||
List<MmInventoryExcelDto> inventoryList = new();
|
||
using (var stream = formFile.OpenReadStream())
|
||
{
|
||
try
|
||
{
|
||
IWorkbook workbook = new XSSFWorkbook(stream);
|
||
ISheet sheet = workbook.GetSheetAt(0);
|
||
|
||
#region 读取excel
|
||
|
||
// 遍历每一行
|
||
for (int row = 1; row <= sheet.LastRowNum; row++)
|
||
{
|
||
IRow currentRow = sheet.GetRow(row);
|
||
if (currentRow != null) // 确保行不为空
|
||
{
|
||
MmInventoryExcelDto inventory = new MmInventoryExcelDto();
|
||
|
||
//00 ID
|
||
NPOI.SS.UserModel.ICell currentCell_00 = currentRow.GetCell(0);
|
||
inventory.Id = (int)currentCell_00?.NumericCellValue;
|
||
|
||
//02物料编码
|
||
NPOI.SS.UserModel.ICell currentCell_01 = currentRow.GetCell(1);
|
||
inventory.MaterialCode = currentCell_01?.ToString();
|
||
if (
|
||
currentCell_01 == null
|
||
|| string.IsNullOrEmpty(inventory.MaterialCode)
|
||
)
|
||
{
|
||
message = $"物料编码不可为空,第{row + 1}行";
|
||
break;
|
||
}
|
||
|
||
//03批次号
|
||
NPOI.SS.UserModel.ICell currentCell_02 = currentRow.GetCell(2);
|
||
inventory.BatchNo = currentCell_02?.ToString() ?? string.Empty;
|
||
|
||
//04当前库存量
|
||
NPOI.SS.UserModel.ICell currentCell_03 = currentRow.GetCell(3);
|
||
string currentQtyStr = currentCell_03?.ToString();
|
||
|
||
if (currentCell_03 == null || string.IsNullOrWhiteSpace(currentQtyStr))
|
||
{
|
||
message = $"当前库存量不可为空,第{row + 1}行";
|
||
break;
|
||
}
|
||
|
||
// 尝试转换为decimal
|
||
if (!decimal.TryParse(currentQtyStr, out decimal currentQty))
|
||
{
|
||
message = $"当前库存量格式错误(必须是数字),第{row + 1}行";
|
||
break;
|
||
}
|
||
|
||
// 验证数值范围(可根据业务需求调整)
|
||
//if (currentQty < 0)
|
||
//{
|
||
// message = $"当前库存量不能为负数,第{row + 1}行";
|
||
// break;
|
||
//}
|
||
inventory.CurrentQty = currentQty;
|
||
|
||
//05 仓库编码
|
||
NPOI.SS.UserModel.ICell currentCell_04 = currentRow.GetCell(4);
|
||
inventory.WarehouseCode = currentCell_04?.ToString();
|
||
if (
|
||
currentCell_04 == null
|
||
|| string.IsNullOrEmpty(inventory.WarehouseCode)
|
||
)
|
||
{
|
||
message = $"仓库编码不可为空,第{row + 1}行";
|
||
break;
|
||
}
|
||
|
||
//06 仓库名称
|
||
NPOI.SS.UserModel.ICell currentCell_05 = currentRow.GetCell(5);
|
||
inventory.WarehouseName = currentCell_05?.ToString();
|
||
if (
|
||
currentCell_05 == null
|
||
|| string.IsNullOrEmpty(inventory.WarehouseName)
|
||
)
|
||
{
|
||
message = $"仓库名称不可为空,第{row + 1}行";
|
||
break;
|
||
}
|
||
|
||
//07 库位编码
|
||
NPOI.SS.UserModel.ICell currentCell_06 = currentRow.GetCell(6);
|
||
inventory.LocationCode = currentCell_06?.ToString();
|
||
if (
|
||
currentCell_06 == null
|
||
|| string.IsNullOrEmpty(inventory.LocationCode)
|
||
)
|
||
{
|
||
message = $"仓库编码不可为空,第{row + 1}行";
|
||
break;
|
||
}
|
||
|
||
//08 库位名称
|
||
NPOI.SS.UserModel.ICell currentCell_07 = currentRow.GetCell(7);
|
||
inventory.LocationName = currentCell_07?.ToString();
|
||
if (
|
||
currentCell_07 == null
|
||
|| string.IsNullOrEmpty(inventory.LocationName)
|
||
)
|
||
{
|
||
message = $"库位名称不可为空,第{row + 1}行";
|
||
break;
|
||
}
|
||
|
||
//09 创建时间
|
||
NPOI.SS.UserModel.ICell currentCell_08 = currentRow.GetCell(8);
|
||
inventory.CreatedTime = currentCell_08?.DateCellValue ?? DateTime.Now;
|
||
|
||
inventoryList.Add(inventory);
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
return null;
|
||
}
|
||
}
|
||
// TODO 3.调用SplitInsert方法实现导入操作,注意主键列的配置(建议优化为,ID相同则修改,不同则新增)
|
||
|
||
var x = Context
|
||
.Storageable(inventoryList)
|
||
//.SplitInsert(it => !it.Any())
|
||
//.WhereColumns(it => it.Id) //如果不是主键可以这样实现(多字段it=>new{it.x1,it.x2})
|
||
.ToStorage();
|
||
var result = x.AsInsertable.ExecuteCommand();
|
||
var result2 = x.AsUpdateable.IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommand(); //插入可插入部分;
|
||
|
||
var importResult = new ImportResultDto
|
||
{
|
||
Message = message,
|
||
Inserted = x.InsertList.Count,
|
||
Updated = x.UpdateList.Count,
|
||
ErrorCount = x.ErrorList.Count,
|
||
IgnoredCount = x.IgnoreList.Count,
|
||
Deleted = x.DeleteList.Count,
|
||
Total = x.TotalList.Count,
|
||
};
|
||
//输出统计
|
||
Console.WriteLine(importResult);
|
||
// 4.收集错误与忽略信息,返回导入结果ImportResultDto 提示,需要修改IServer相关返回格式
|
||
foreach (var item in x.ErrorList)
|
||
{
|
||
importResult.Errors.Add(
|
||
new ImportErrorDto
|
||
{
|
||
MaterialCode = item.Item.MaterialCode,
|
||
Message = item.StorageMessage,
|
||
}
|
||
);
|
||
}
|
||
foreach (var item in x.IgnoreList)
|
||
{
|
||
importResult.Ignored.Add(
|
||
new ImportErrorDto
|
||
{
|
||
MaterialCode = item.Item.MaterialCode,
|
||
Message = item.StorageMessage,
|
||
}
|
||
);
|
||
}
|
||
|
||
return importResult;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 导出物料表列表
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
public PagedInfo<MmInventoryExcelDto> SelectInventoryList(
|
||
MmInventoryQueryDto inventory,
|
||
PagerInfo pager
|
||
)
|
||
{
|
||
// Use the same predicate builder as GetList to support consistent filtering
|
||
var predicate = QueryExp(inventory);
|
||
|
||
var query = Queryable()
|
||
.Where(predicate.ToExpression())
|
||
.Select(it => new MmInventoryExcelDto
|
||
{
|
||
Id = it.Id,
|
||
MaterialCode = it.MaterialCode,
|
||
BatchNo = it.BatchNo,
|
||
CurrentQty = it.CurrentQty,
|
||
WarehouseCode = it.WarehouseCode,
|
||
WarehouseName = it.WarehouseName,
|
||
LocationCode = it.LocationCode,
|
||
LocationName = it.LocationName,
|
||
CreatedTime = it.CreatedTime,
|
||
});
|
||
|
||
return query.ToPage(pager);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 查询出/入记录列表
|
||
/// </summary>
|
||
/// <param name="parm"></param>
|
||
/// <returns></returns>
|
||
public PagedInfo<MmInventoryRecordDto> GetInOrOutRecord(MmInventoryRecordQueryDto parm)
|
||
{
|
||
PagedInfo<MmInventoryRecordDto> result = new PagedInfo<MmInventoryRecordDto>();
|
||
// 处理日期
|
||
if (parm.StartTime != null && parm.StartTime.Value > DateTime.MinValue)
|
||
{
|
||
parm.StartTime = DOANConvertDate.ConvertLocalDate(parm.StartTime.Value);
|
||
}
|
||
if (parm.EndTime != null && parm.EndTime.Value > DateTime.MinValue)
|
||
{
|
||
parm.EndTime = DOANConvertDate.ConvertLocalDate(parm.EndTime.Value);
|
||
}
|
||
// 查询入库记录
|
||
if (parm.SearchType == 1)
|
||
{
|
||
result = Context
|
||
.Queryable<MmRecordInbound>()
|
||
.WhereIF(
|
||
parm.StartTime != null && parm.StartTime.Value > DateTime.MinValue,
|
||
it => it.CreatedTime >= parm.StartTime
|
||
)
|
||
.WhereIF(
|
||
parm.EndTime != null && parm.EndTime.Value > DateTime.MinValue,
|
||
it => it.CreatedTime <= parm.EndTime
|
||
)
|
||
.WhereIF(
|
||
!string.IsNullOrEmpty(parm.TransactionType),
|
||
it => it.TransactionType == parm.TransactionType
|
||
)
|
||
.Where(it => it.MaterialCode == parm.MaterialCode)
|
||
.Where(it => it.SupplierCode == parm.SupplierCode)
|
||
.Where(it => it.LocationCode == parm.LocationCode)
|
||
.Where(it => it.BatchNo == parm.BatchNo)
|
||
.Select(it => new MmInventoryRecordDto()
|
||
{
|
||
Id = it.Id,
|
||
InboundNo = it.InboundNo,
|
||
MaterialCode = it.MaterialCode,
|
||
MaterialName = it.MaterialName,
|
||
SupplierCode = it.SupplierCode,
|
||
SupplierName = it.SupplierName,
|
||
LocationCode = it.LocationCode,
|
||
LocationName = it.LocationName,
|
||
WarehouseCode = it.WarehouseCode,
|
||
WarehouseName = it.WarehouseName,
|
||
BatchNo = it.BatchNo,
|
||
Quantity = it.Quantity,
|
||
TransactionType = it.TransactionType,
|
||
Operator = it.Operator,
|
||
CreatedTime = it.CreatedTime,
|
||
Workorder = it.Workorder,
|
||
WorkorderRaw = it.WorkorderRaw,
|
||
StoveCode = it.StoveCode,
|
||
Remarks = it.Remarks,
|
||
})
|
||
.OrderByDescending(it => it.CreatedTime)
|
||
.ToPage(parm);
|
||
}
|
||
// 查询出库记录
|
||
else if (parm.SearchType == 2)
|
||
{
|
||
result = Context
|
||
.Queryable<MmRecordOutbound>()
|
||
.WhereIF(
|
||
parm.StartTime != null && parm.StartTime.Value > DateTime.MinValue,
|
||
it => it.CreatedTime >= parm.StartTime
|
||
)
|
||
.WhereIF(
|
||
parm.EndTime != null && parm.EndTime.Value > DateTime.MinValue,
|
||
it => it.CreatedTime <= parm.EndTime
|
||
)
|
||
.WhereIF(
|
||
!string.IsNullOrEmpty(parm.TransactionType),
|
||
it => it.TransactionType == parm.TransactionType
|
||
)
|
||
.Where(it => it.MaterialCode == parm.MaterialCode)
|
||
//.Where(it => it.SupplierCode == parm.SupplierCode)
|
||
.Where(it => it.LocationCode == parm.LocationCode)
|
||
.Where(it => it.BatchNo == parm.BatchNo)
|
||
.Select(it => new MmInventoryRecordDto()
|
||
{
|
||
Id = it.Id,
|
||
OutboundNo = it.OutboundNo,
|
||
MaterialCode = it.MaterialCode,
|
||
MaterialName = it.MaterialName,
|
||
LocationCode = it.LocationCode,
|
||
LocationName = it.LocationName,
|
||
WarehouseCode = it.WarehouseCode,
|
||
WarehouseName = it.WarehouseName,
|
||
BatchNo = it.BatchNo,
|
||
Quantity = it.Quantity,
|
||
TransactionType = it.TransactionType,
|
||
Operator = it.Operator,
|
||
CreatedTime = it.CreatedTime,
|
||
Workorder = it.Workorder,
|
||
WorkorderRaw = it.WorkorderRaw,
|
||
OrderNo = it.OrderNo,
|
||
Remarks = it.Remarks,
|
||
})
|
||
.OrderByDescending(it => it.CreatedTime)
|
||
.ToPage(parm);
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 撤销单据,传入单据类型(1-入库单,2-出库单)和ID
|
||
/// </summary>
|
||
/// <param name="parm"></param>
|
||
/// <returns>返回ok即为成功其他都是不成功</returns>
|
||
/// <exception cref="NotImplementedException"></exception>
|
||
public string RevokeReceipt(MmInventoryRevokeDto parm)
|
||
{
|
||
try
|
||
{
|
||
int _type = parm.Type;
|
||
int _id = parm.Id;
|
||
if (_type < -1 && _id < -1)
|
||
{
|
||
return $"传入参数有误,请检查:type-{_type},id-{_id}";
|
||
}
|
||
// type == 1 入库单
|
||
if (_type == 1)
|
||
{
|
||
MmRecordInbound recordInbound = Context
|
||
.Queryable<MmRecordInbound>()
|
||
.Where(it => it.Id == _id)
|
||
.First();
|
||
if (recordInbound == null)
|
||
{
|
||
return $"无此入库记录,请检查:type-{_type},id-{_id}";
|
||
}
|
||
if (recordInbound.Remarks == "已撤销")
|
||
{
|
||
return $"此记录已撤销过,不可重复撤销";
|
||
}
|
||
//做出库红单
|
||
InboundReceiptDto revokeRecepitDto = new()
|
||
{
|
||
ReceiptType = 2,
|
||
MaterialCode = recordInbound.MaterialCode,
|
||
BatchNo = recordInbound.BatchNo,
|
||
LocationCode = recordInbound.LocationCode,
|
||
WarehouseCode = recordInbound.WarehouseCode,
|
||
SupplierCode = recordInbound.SupplierCode,
|
||
StoveCode = recordInbound.StoveCode,
|
||
Workorder = recordInbound.Workorder,
|
||
WorkorderRaw = recordInbound.WorkorderRaw,
|
||
Operator = recordInbound.Operator,
|
||
Quantity = recordInbound.Quantity,
|
||
TransactionType = "入库红单",
|
||
Remarks = $"撤销操作,入库单号:{recordInbound.InboundNo}",
|
||
};
|
||
string result = CreateInboundReceipt(revokeRecepitDto);
|
||
if (result == "ok")
|
||
{
|
||
recordInbound.Remarks = "已撤销";
|
||
Context.Updateable(recordInbound).ExecuteCommand();
|
||
return result;
|
||
}
|
||
else
|
||
{
|
||
return result;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
MmRecordOutbound recordOutbound = Context
|
||
.Queryable<MmRecordOutbound>()
|
||
.Where(it => it.Id == _id)
|
||
.First();
|
||
if (recordOutbound == null)
|
||
{
|
||
return $"无此出库记录,请检查:type-{_type},id-{_id}";
|
||
}
|
||
if (recordOutbound.Remarks == "已撤销")
|
||
{
|
||
return $"此记录已撤销过,不可重复撤销";
|
||
}
|
||
//做出库红单
|
||
OutboundReceiptDto revokeRecepitDto = new()
|
||
{
|
||
ReceiptType = 2,
|
||
MaterialCode = recordOutbound.MaterialCode,
|
||
BatchNo = recordOutbound.BatchNo,
|
||
LocationCode = recordOutbound.LocationCode,
|
||
WarehouseCode = recordOutbound.WarehouseCode,
|
||
OrderNo = recordOutbound.OrderNo,
|
||
Workorder = recordOutbound.Workorder,
|
||
WorkorderRaw = recordOutbound.WorkorderRaw,
|
||
Operator = recordOutbound.Operator,
|
||
Quantity = recordOutbound.Quantity,
|
||
TransactionType = "出库红单",
|
||
Remarks = $"撤销操作,出库单号:{recordOutbound.OutboundNo}",
|
||
};
|
||
string result = CreateOutboundReceipt(revokeRecepitDto);
|
||
if (result == "ok")
|
||
{
|
||
recordOutbound.Remarks = "已撤销";
|
||
Context.Updateable(recordOutbound).ExecuteCommand();
|
||
return result;
|
||
}
|
||
else
|
||
{
|
||
return result;
|
||
}
|
||
}
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
return e.Message;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 出货操作 成功返回ok
|
||
/// </summary>
|
||
/// <param name="parm"></param>
|
||
/// <returns></returns>
|
||
public string Shipment(ShipmentDto 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();
|
||
|
||
// 订单关联处理
|
||
if (!string.IsNullOrEmpty(parm.CustomerOrder))
|
||
{
|
||
// 判断订单号是否存在
|
||
var orderPurchase = Context
|
||
.Queryable<OrderPurchase>()
|
||
.Where(o => o.OrderNoMes == parm.CustomerOrder)
|
||
.First();
|
||
if (orderPurchase == null)
|
||
{
|
||
Context.Ado.RollbackTran();
|
||
return "订单号不存在";
|
||
}
|
||
|
||
// 判断工单是否存在
|
||
if (!string.IsNullOrEmpty(parm.Workorder))
|
||
{
|
||
var workorderInfo = Context
|
||
.Queryable<ProWorkorder>()
|
||
.Where(it => it.Workorder == parm.Workorder)
|
||
.First();
|
||
if (workorderInfo == null)
|
||
{
|
||
Context.Ado.RollbackTran();
|
||
return "工单不存在";
|
||
}
|
||
|
||
// 判断工单主体型号和订单物料号是否匹配
|
||
if (workorderInfo.productionCode != orderPurchase.MaterialCode)
|
||
{
|
||
Context.Ado.RollbackTran();
|
||
return "工单主体型号和订单物料号不匹配";
|
||
}
|
||
}
|
||
}
|
||
|
||
// 获取现有库存
|
||
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)
|
||
{
|
||
if (parm.ReceiptType == 1)
|
||
{
|
||
Context.Ado.RollbackTran();
|
||
return "库存不存在,禁止出货!";
|
||
}
|
||
// 红单处理
|
||
var newInventory = new MmInventory()
|
||
{
|
||
MaterialCode = mmMaterial.MaterialCode,
|
||
MaterialName = mmMaterial.MaterialName,
|
||
SupplierCode = mmMaterial.SupplierCode,
|
||
SupplierName = mmMaterial.SupplierName,
|
||
LocationCode = mmLocation.LocationCode,
|
||
LocationName = mmLocation.LocationName,
|
||
WarehouseCode = mmLocation.WarehouseCode,
|
||
WarehouseName = mmLocation.WarehouseName,
|
||
BatchNo = parm.BatchNo,
|
||
CurrentQty = -delta,
|
||
Unit = mmMaterial.Unit,
|
||
LastUpdatedTime = null,
|
||
CreatedTime = nowDate,
|
||
};
|
||
Context.Insertable(newInventory).ExecuteCommand();
|
||
}
|
||
else
|
||
{
|
||
if (mmInventory.CurrentQty - delta < 0)
|
||
{
|
||
Context.Ado.RollbackTran();
|
||
return "库存不足,无法出货!";
|
||
}
|
||
// 更新库存
|
||
mmInventory.CurrentQty -= delta;
|
||
Context
|
||
.Updateable(mmInventory)
|
||
.UpdateColumns(it => it.CurrentQty)
|
||
.ExecuteCommand();
|
||
}
|
||
|
||
// 生成出货单号
|
||
var shipmentNo = GenerateReceiptNo("CH");
|
||
|
||
// 创建出货记录
|
||
MmRecordOutbound newRecord = new()
|
||
{
|
||
OutboundNo = shipmentNo,
|
||
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 = -delta,
|
||
Unit = mmMaterial.Unit,
|
||
CreatedTime = nowDate,
|
||
TransactionType = parm.TransactionType,
|
||
Workorder = parm.Workorder,
|
||
WorkorderRaw = parm.WorkorderRaw,
|
||
OrderNo = parm.CustomerOrder,
|
||
Remarks = parm.Remarks,
|
||
};
|
||
Context.Insertable(newRecord).ExecuteCommand();
|
||
|
||
// 更新工单和订单信息
|
||
if (
|
||
!string.IsNullOrEmpty(parm.CustomerOrder)
|
||
&& !string.IsNullOrEmpty(parm.Workorder)
|
||
)
|
||
{
|
||
// 获取当前工单信息
|
||
var workorderInfo = Context
|
||
.Queryable<ProWorkorder>()
|
||
.Where(it => it.Workorder == parm.Workorder)
|
||
.First();
|
||
|
||
// 计算累计出货数量(使用delta值,考虑单据类型的影响)
|
||
int currentShipmentNum = workorderInfo.ShipmentNum ?? 0;
|
||
int newShipmentNum = currentShipmentNum + (int)delta;
|
||
|
||
// 验证出货数量有效性
|
||
if (newShipmentNum < 0)
|
||
{
|
||
Context.Ado.RollbackTran();
|
||
return "累计出货数量不能为负数";
|
||
}
|
||
|
||
// 更新工单信息
|
||
Context
|
||
.Updateable<ProWorkorder>()
|
||
.Where(it => it.Workorder == parm.Workorder)
|
||
.SetColumns(it => it.ShipmentNum == newShipmentNum)
|
||
.SetColumns(it => it.CustomerOrder == parm.CustomerOrder)
|
||
.ExecuteCommand();
|
||
|
||
// 修改采购订单信息
|
||
var orderPurchase = Context
|
||
.Queryable<OrderPurchase>()
|
||
.Where(o => o.OrderNoMes == parm.CustomerOrder)
|
||
.First();
|
||
if (orderPurchase != null)
|
||
{
|
||
int newQuantity =
|
||
Context
|
||
.Queryable<ProWorkorder>()
|
||
.Where(it => it.CustomerOrder == parm.CustomerOrder)
|
||
.Sum(it => it.ShipmentNum)
|
||
?? 0;
|
||
|
||
orderPurchase.DeliveryQuantity = newQuantity;
|
||
if (orderPurchase.DeliveryQuantity > orderPurchase.DemandQuantity)
|
||
{
|
||
Context.Ado.RollbackTran();
|
||
return "交货数量超过订单需求数量";
|
||
}
|
||
if (orderPurchase.DeliveryQuantity == orderPurchase.DemandQuantity)
|
||
{
|
||
orderPurchase.Orderindicator = 1;
|
||
}
|
||
else
|
||
{
|
||
orderPurchase.Orderindicator = 0;
|
||
}
|
||
Context.Updateable(orderPurchase).ExecuteCommand();
|
||
}
|
||
}
|
||
|
||
// 提交事务
|
||
Context.Ado.CommitTran();
|
||
return "ok";
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
// 回滚操作
|
||
Context.Ado.RollbackTran();
|
||
return ex.Message;
|
||
}
|
||
}
|
||
}
|
||
}
|