Files
BarCode-Api/src/BarCode.Web.Domain/Services/SerialNumberService.cs
2025-08-04 14:36:26 +08:00

633 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 BarCode.Web.Core.Dto;
using BarCode.Web.Core.Dto.Erp;
using BarCode.Web.Core.Dto.Login;
using BarCode.Web.Core.Dto.SerialNumbers;
using BarCode.Web.Core.Internal.Results;
using BarCode.Web.Domain.Entitys;
using BarCode.Web.Domain.Infrastructure;
using BarCode.Web.Domain.IService;
using BarCode.Web.Domain.IService.Public;
using BarCode.Web.Domain.Services.Public;
using BarCode.Web.Domain.Values;
using BarCode.Web.Domain.Values.Single;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using NPOI.HPSF;
using NPOI.HSSF.Record;
using NPOI.OpenXmlFormats.Wordprocessing;
using Org.BouncyCastle.Crypto;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BarCode.Web.Domain.Services
{
/// <summary>
/// 序列号服务
/// </summary>
public class SerialNumberService : ISerialNumberService
{
private readonly ISerialNumbersRepositories _serialNumbersRepositories;
private readonly ISGenerateRecordRepositories _sGenerateRecordRepositories;
private readonly RedisClientService _redisClientService;
private readonly IServiceScopeFactory _serviceScopeFactory;
private readonly ILogger<SerialNumberService> _logger;
private IBasicsRepositories _transactionRepositories;
private ICenerateDataRepositories _cenerateDataRepositories;
private readonly ISingleDataService _singleDataService;
private readonly IErpService _erpService;
/// <summary>
/// 序列号服务
/// </summary>
/// <param name="serialNumbersRepositories"></param>
/// <param name="sGenerateRecordRepositories"></param>
/// <param name="redisClientService"></param>
/// <param name="serviceScopeFactory"></param>
/// <param name="logger"></param>
/// <param name="transactionRepositories"></param>
/// <param name="cenerateDataRepositories"></param>
public SerialNumberService(ISerialNumbersRepositories serialNumbersRepositories,
ISGenerateRecordRepositories sGenerateRecordRepositories,
RedisClientService redisClientService,
IServiceScopeFactory serviceScopeFactory,
ILogger<SerialNumberService> logger, IBasicsRepositories transactionRepositories,
ICenerateDataRepositories cenerateDataRepositories, ISingleDataService singleDataService, IErpService erpService)
{
_serialNumbersRepositories = serialNumbersRepositories;
_sGenerateRecordRepositories = sGenerateRecordRepositories;
_redisClientService = redisClientService;
_serviceScopeFactory = serviceScopeFactory;
_logger = logger;
_transactionRepositories = transactionRepositories;
_cenerateDataRepositories = cenerateDataRepositories;
_singleDataService = singleDataService;
_erpService = erpService;
}
/// <summary>
/// 生成序列号
/// </summary>
/// <param name="dto"></param>
/// <param name="loginInfo"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public Task<Result> Generate(GenerateSerialNumberRequest dto, LoginInDto loginInfo)
{
if (dto.Details.Count() == 0) return Task.FromResult(Result.ReSuccess());
//if (dto.Details.Count() > 1000) return Task.FromResult(Result.ReFailure(ResultCodes.SerialGenerateBigNumber));
_logger.LogInformation($"生成序列号:{JsonConvert.SerializeObject(dto)},用户:{loginInfo.UserInfo.Nickname}");
var info = _redisClientService.GetStringKey<bool>($"barcode_cenerate_serial");
if (info == true) return Task.FromResult(Result.ReFailure(ResultCodes.SerialNumberG));
_redisClientService.SetStringKey($"barcode_cenerate_serial", true, TimeSpan.FromMinutes(5));
var materials_result = _erpService.BillQueryForMaterial().GetAwaiter().GetResult();
List<ErpMaterialDto> materials = new List<ErpMaterialDto>();
if (materials_result.IsSuccess)
materials = materials_result.Data.ToList();
var cList = dto.Details.GroupBy(g => g.Specifications).Select(s => s.Key).ToList();
foreach (var s in cList)
{
var m = materials.FirstOrDefault(w => w.Specifications.Equals(s));
var details = dto.Details.Where(w => w.Specifications.Equals(s)).ToList();
if (m == null)
{
details.ForEach(f => dto.Details.Remove(f));
}
else
{
foreach (var de in details)
{
de.MaterialNumber = m.MaterialNumber;
de.IdConvertBar = m.IdConvertBar;
}
}
}
string supplierCode = "";
string orgCode = "";
if (dto.OrgCode.Substring(0, 1).Equals("s"))
supplierCode = dto.OrgCode.Substring(2, dto.OrgCode.Length - 2);
else
orgCode = dto.OrgCode.Substring(2, dto.OrgCode.Length - 2);
var dataEntity = _cenerateDataRepositories.Get(CenerateDataType.Serial).GetAwaiter().GetResult();
int beginNumber = dataEntity.Number;
if (beginNumber == 0)
dataEntity.Number = dto.Details.Sum(s => s.Number);
else
dataEntity.Number += dto.Details.Sum(s => s.Number);
List<SerialNumberGenerateRecord> sgList = new List<SerialNumberGenerateRecord>();
foreach (var d in dto.Details)
{
if(d.Number>1000)
{
d.Number = 1000;
}
if (d.isTwo == 0)//如果套装数为0那么自动变成1
{
d.isTwo = 1;
}
else if(d.isTwo==2)
{
int result = d.Number % d.isTwo;
if (result !=0)//
{
return Task.FromResult(Result.ReFailure(ResultCodes.IsTwoError));
}
}
else if(d.isTwo>2)
{
return Task.FromResult(Result.ReFailure(ResultCodes.IsTwoError));
}
SerialNumberGenerateRecord sg = new SerialNumberGenerateRecord()
{
CompanyId = loginInfo.UserInfo.CompanyId,
CreateTime = DateTime.Now,
CreatorId = loginInfo.UserInfo.UcId,
OrgCode = orgCode,
IdConvertBar = d.IdConvertBar,
MaterialNumber = d.MaterialNumber,
Number = d.Number,
BeginNumber = beginNumber,
PurchaseBillNo = d.PurchaseBillNo,
SupplierCode = supplierCode,
IsTwo=d.isTwo//alter by yzh
};
//下一个物料开始数量要重新赋值
beginNumber = beginNumber + d.Number;
sgList.Add(sg);
}
IDbContextTransaction _transaction = _transactionRepositories.GetTransaction();
bool res_Rollback = false;
var isSuccess = _sGenerateRecordRepositories.AddRange(sgList, false).GetAwaiter().GetResult();
if (!isSuccess) res_Rollback = true;
if (!res_Rollback)
{
var entity = _cenerateDataRepositories.Edit(dataEntity, false).GetAwaiter().GetResult();
if (entity == null) res_Rollback = true;
}
isSuccess = _transactionRepositories.CommitTransaction(res_Rollback, _transaction);
if (!isSuccess) return Task.FromResult(Result.ReFailure(ResultCodes.DateWriteError));
Task.Run(async () =>
{
await GenerateSerialNumber(sgList);
});
_redisClientService.SetStringKey($"barcode_cenerate_serial", false, TimeSpan.FromMinutes(5));
return Task.FromResult(Result.ReSuccess());
}
/// <summary>
/// 循环生成序列码
/// </summary>
/// <param name="sgList"></param>
/// <param name="beginNumber"></param>
private async Task GenerateSerialNumber(List<SerialNumberGenerateRecord> sgList)
{
try
{
var info = _redisClientService.GetStringKey<bool>($"cenerate_serial_exec");
if (info == true)
{
//如果当前有在生成的计划 则挂起 等生成完成
while (true)
{
Thread.Sleep(5000);
info = _redisClientService.GetStringKey<bool>($"cenerate_serial_exec");
if (info != true)
break;
}
}
_redisClientService.SetStringKey($"cenerate_serial_exec", true, TimeSpan.FromMinutes(30));
_logger.LogInformation($"生成序列码开始:{DateTime.Now}-{JsonConvert.SerializeObject(sgList)}");
using (var scope = _serviceScopeFactory.CreateScope())
{
bool isSuccess = true;
bool res_Rollback = false;
var _snRepositories = scope.ServiceProvider.GetRequiredService<ISerialNumbersRepositories>();
var _sgRepositories = scope.ServiceProvider.GetRequiredService<ISGenerateRecordRepositories>();
_transactionRepositories = scope.ServiceProvider.GetRequiredService<IBasicsRepositories>();
foreach (var sg in sgList)
{
List<SerialNumbers> sList = new List<SerialNumbers>();
for (int i = 0; i < sg.Number; i++)
{
SerialNumbers s = new SerialNumbers()
{
CreateTime = DateTime.Now,
CreatorId = sg.CreatorId,
OrgCode = sg.OrgCode,
SupplierCode = sg.SupplierCode,
SerialNumber = sg.IdConvertBar,
MaterialNumber = sg.MaterialNumber,
Number = sg.BeginNumber + i,
IsTwo = sg.IsTwo,
thisNumber = i+1,//alter by yzh
GenerateRecordId = sg.Id
};
sList.Add(s);
}
//一个生成记录一个事物,这样能一条条记录对应的生成下去 成功一个是一个
IDbContextTransaction _transaction = _transactionRepositories.GetTransaction();
var isRes = await _snRepositories.AddRange(sList, false);
if (!isRes)
res_Rollback = true;
if (!res_Rollback)
{
sg.Complete();//生成完成
var sg_entity = await _sgRepositories.Edit(sg, false);
if (sg_entity == null)
res_Rollback = true;
}
//提交事务
isSuccess = _transactionRepositories.CommitTransaction(res_Rollback, _transaction);
if (res_Rollback || !isSuccess)
_logger.LogError("生成序列码数据操作失败");
}
}
_redisClientService.SetStringKey($"cenerate_serial_exec", false, TimeSpan.FromMinutes(30));
_logger.LogInformation($"生成序列码结束{DateTime.Now}");
}
catch (Exception ex)
{
_logger.LogError($"生成序列码异常:{ex.ToString}");
}
}
/// <summary>
/// 下载
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public async Task<Result> DownLoad(OperateSerialNumberRequest dto)
{
//取出所有的生成记录
var generateRecords = await _sGenerateRecordRepositories.GetEntityList(dto.GenerateRecordIds,"0");
if (generateRecords.Count() != dto.GenerateRecordIds.Count())
return Result.ReFailure(ResultCodes.NoDateError);
var snGRList = await _serialNumbersRepositories.GetEntityListByGRIds(dto.GenerateRecordIds);
//修改序列号下载数
List<SerialNumbers> olist = new List<SerialNumbers>();
if (dto.IsAll)
olist = snGRList;
else
{
if (dto.IsTwo == 2)//说明为两件装
{
var olistTmp=snGRList.Where(w => dto.SerialNumbers.Contains(w.SerialNumber)).ToList();
List<string> s = new List<string>();
for (var i = 0; i < olistTmp.Count; i++)
{
string[] y= olistTmp[i].TwoSerialNumber.Split(',');
s.Add(y[0]);
s.Add(y[1]);
}
s.Distinct();
var snGRList2 = await _serialNumbersRepositories.GetEntityList(s);
olist=snGRList2;
}
else
{
olist = snGRList.Where(w => dto.SerialNumbers.Contains(w.SerialNumber)).ToList();
}
//olist = snGRList.Where(w => dto.SerialNumbers.Contains(w.TwoSerialNumber)).ToList();
}
olist.ForEach(f => f.DownLoad());
if(dto.IsTwo == 2)
{
snGRList.Union(olist);
}
foreach (var g in generateRecords)
{
int downLoad = snGRList.Where(w => w.GenerateRecordId == g.Id && w.DownLoadNumber > 0).Count();
g.DownLoad(downLoad);
}
IDbContextTransaction _transaction = _transactionRepositories.GetTransaction();
bool res_Rollback = false;
var isSuccess = await _serialNumbersRepositories.EditEntityList(olist, false);
if (!isSuccess) res_Rollback = true;
if (!res_Rollback)
{
var res = await _sGenerateRecordRepositories.EditEntityList(generateRecords, false);
if (!res) res_Rollback = true;
}
isSuccess = _transactionRepositories.CommitTransaction(res_Rollback, _transaction);
if (!isSuccess) return Result.ReFailure(ResultCodes.DateWriteError);
return Result.ReSuccess();
}
/// <summary>
/// 更新错的Sn
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public async Task<Result> UpdateSn(OperateSerialNumberRequest dto)
{
//取出所有的生成记录
var generateRecords = await _sGenerateRecordRepositories.GetEntityList(dto.GenerateRecordIds,"1");
List<SerialNumbers> olist = new List<SerialNumbers>();
bool res_Rollback = false;
for (int i=0;i< generateRecords.Count;i++)
{
List<int> s = [];
string newSuitNumber = "";
string oldSuitNumber = "";
int ids = generateRecords[i].Id;
s.Add(ids);
olist = await _serialNumbersRepositories.GetEntityListByGRIds(s);
//修改序列号下载数
int m=0;
foreach (var item in olist)
{
m++;
//自动生成序列码
string sn = item.SerialNumber;
if (m % 2 == 0)
{
newSuitNumber = oldSuitNumber;
}
else
{
oldSuitNumber = sn;
newSuitNumber = sn;
}
item.GenerateSuitNumber(newSuitNumber);
// item.GenerateTwoSerialNumber(newSuitNumber);
item.SetThisNumber(m);
item.IsTwo = 2;
}
foreach (var item in olist)
{
string ss = _serialNumbersRepositories.GetTwoSerialNumber(olist, item.SuitNumber);
item.GenerateTwoSerialNumber(ss);
string sNumberCode = _serialNumbersRepositories.GetTwoNumberCode(olist, item.SuitNumber);
item.GenerateTwoNumberCode(sNumberCode);
}
IDbContextTransaction _transaction = _transactionRepositories.GetTransaction();
var isSuccess = await _serialNumbersRepositories.EditEntityList(olist, false);
if (!isSuccess) res_Rollback = true;
generateRecords[i].IsTwo = 2;
isSuccess = _transactionRepositories.CommitTransaction(res_Rollback, _transaction);
if (!isSuccess) return Result.ReFailure(ResultCodes.DateWriteError);
//return Result.ReSuccess();
}
if (!res_Rollback)
{
var res = await _sGenerateRecordRepositories.EditEntityList(generateRecords, false);
if (!res) res_Rollback = true;
}
return Result.ReSuccess();
}
/// <summary>
/// 转换序列号(从单件装转为两件装)
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public async Task<Result> TransferSn(TransferSNOneTwoTwoRequest dto)
{
//取出所有的生成记录
var generateRecords = await _sGenerateRecordRepositories.GetEntityList(dto.ids, "0");
for (int i = 0; i < generateRecords.Count; i++)
{
int intNum = generateRecords[i].Number;
int result = intNum % 2;
if (result != 0)//
{
return Result.ReFailure(ResultCodes.IsTwoError);
}
}
List<SerialNumbers> olist = new List<SerialNumbers>();
bool res_Rollback = false;
for (int i = 0; i < generateRecords.Count; i++)
{
List<int> s = [];
string newSuitNumber = "";
string oldSuitNumber = "";
int ids = generateRecords[i].Id;
s.Add(ids);
olist = await _serialNumbersRepositories.GetEntityListByGRIds(s);
//修改序列号下载数
int m = 0;
foreach (var item in olist)
{
m++;
//自动生成序列码
string sn = item.SerialNumber;
if (m % 2 == 0)
{
newSuitNumber = oldSuitNumber;
}
else
{
oldSuitNumber = sn;
newSuitNumber = sn;
}
item.GenerateSuitNumber(newSuitNumber);
// item.GenerateTwoSerialNumber(newSuitNumber);
item.SetThisNumber(m);
item.IsTwo = 2;
}
foreach (var item in olist)
{
string ss = _serialNumbersRepositories.GetTwoSerialNumber(olist, item.SuitNumber);
item.GenerateTwoSerialNumber(ss);
string sNumberCode = _serialNumbersRepositories.GetTwoNumberCode(olist, item.SuitNumber);
item.GenerateTwoNumberCode(sNumberCode);
}
IDbContextTransaction _transaction = _transactionRepositories.GetTransaction();
var isSuccess = await _serialNumbersRepositories.EditEntityList(olist, false);
if (!isSuccess) res_Rollback = true;
generateRecords[i].IsTwo = 2;
isSuccess = _transactionRepositories.CommitTransaction(res_Rollback, _transaction);
if (!isSuccess) return Result.ReFailure(ResultCodes.DateWriteError);
//return Result.ReSuccess();
}
if (!res_Rollback)
{
var res = await _sGenerateRecordRepositories.EditEntityList(generateRecords, false);
if (!res) res_Rollback = true;
}
return Result.ReSuccess();
}
/// <summary>
/// 打印
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public async Task<Result> Print(OperateSerialNumberRequest dto)
{
//取出所有的生成记录
var generateRecords = await _sGenerateRecordRepositories.GetEntityList(dto.GenerateRecordIds,"");
if (generateRecords.Count() != dto.GenerateRecordIds.Count())
return Result.ReFailure(ResultCodes.NoDateError);
var snGRList = await _serialNumbersRepositories.GetEntityListByGRIds(dto.GenerateRecordIds);
//修改序列号下载数
List<SerialNumbers> olist = new List<SerialNumbers>();
if (dto.IsAll)
olist = snGRList;
else
{
olist = snGRList.Where(w => dto.SerialNumbers.Contains(w.SerialNumber)).ToList();
}
olist.ForEach(f => f.Print());
foreach (var g in generateRecords)
{
int printNumber = snGRList.Where(w => w.GenerateRecordId == g.Id && w.PrintNumber > 0).Count();
g.Print(printNumber);
}
IDbContextTransaction _transaction = _transactionRepositories.GetTransaction();
bool res_Rollback = false;
var isSuccess = await _serialNumbersRepositories.EditEntityList(olist, false);
if (!isSuccess) res_Rollback = true;
if (!res_Rollback)
{
var res = await _sGenerateRecordRepositories.EditEntityList(generateRecords, false);
if (!res) res_Rollback = true;
}
isSuccess = _transactionRepositories.CommitTransaction(res_Rollback, _transaction);
if (!isSuccess) return Result.ReFailure(ResultCodes.DateWriteError);
return Result.ReSuccess();
}
/// <summary>
/// 反写使用数
/// </summary>
/// <param name="sGIds"></param>
/// <returns></returns>
public async Task<Result> Use(List<int> sGIds)
{
var sGList = await _sGenerateRecordRepositories.GetEntityList(sGIds,"");
//_logger.LogInformation($"获取到sGList:{JsonConvert.SerializeObject(sGList)}");
var sGSNumberList = await _serialNumbersRepositories.GetEntityListByGRIds(sGIds);
// _logger.LogInformation($"获取到sGSNumberList:{JsonConvert.SerializeObject(sGSNumberList)}");
foreach (var sg in sGList)
{
int number = sGSNumberList.Where(w => w.GenerateRecordId == sg.Id && w.BoxId > 0 ).Count();
sg.Use(number);
// _logger.LogInformation($"获取到sg:{sg}");
}
var isSuccess = await _sGenerateRecordRepositories.EditEntityList(sGList, false);
if (!isSuccess) return Result.ReFailure(ResultCodes.DateWriteError);
return Result.ReSuccess();
}
/// <summary>
/// 修改序列码物料
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public async Task<Result> UpdateMaterial(UpdateMaterialRequest dto)
{
//取出所有的生成记录
var generateRecord = await _sGenerateRecordRepositories.GetEntity(dto.GenerateRecordId);
if (generateRecord == null)
return Result.ReFailure(ResultCodes.NoDateError);
var serialNumbers = await _serialNumbersRepositories.GetEntityList(dto.SerialNumbers);
var exec_m = serialNumbers.Where(w => w.MaterialNumber == dto.MaterialNumber).Select(s => s.MaterialNumber).ToList();
if (exec_m.Count() > 0)
return Result.ReFailure($"序列号{string.Join(",", exec_m)}对应物料跟需要修改的物料一致", 611007);
//修改物料
foreach (var s in serialNumbers)
{
var res = s.UpdateMaterial(dto.MaterialNumber);
if (!res.IsSuccess) return res;
}
generateRecord.UpdateMaterial();
IDbContextTransaction _transaction = _transactionRepositories.GetTransaction();
bool res_Rollback = false;
var isSuccess = await _serialNumbersRepositories.EditEntityList(serialNumbers, false);
if (!isSuccess) res_Rollback = true;
if (!res_Rollback)
{
var res = await _sGenerateRecordRepositories.Edit(generateRecord, false);
if (res == null) res_Rollback = true;
}
isSuccess = _transactionRepositories.CommitTransaction(res_Rollback, _transaction);
if (!isSuccess) return Result.ReFailure(ResultCodes.DateWriteError);
return Result.ReSuccess();
}
}
}