Files
WorkFlowCheck/src/WorkFlowCheck.BL/Services/NumberGeneratorServices.cs
T

165 lines
6.0 KiB
C#

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Storage;
using Serilog;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WorkFlowCheck.BL.Services.Interfaces;
using WorkFlowCheck.Common.DTO;
using WorkFlowCheck.DL;
using WorkFlowCheck.DL.Entities;
namespace WorkFlowCheck.BL.Services
{
public class NumberGeneratorService : INumberGeneratorService
{
private readonly AppDbContext _dbContext;
private static readonly Dictionary<int, SemaphoreSlim> _templateLocks = new();
public NumberGeneratorService(AppDbContext dbContext)
{
_dbContext = dbContext;
}
public async Task<string> GenerateNextNumberAsync(int templateId, IDbContextTransaction transaction, DateTime? baseDate = null)
{
var semaphore = GetOrCreateSemaphore(templateId);
await semaphore.WaitAsync();
try
{
var template = await _dbContext.Set<NumberGeneratorTemplate>()
.FirstOrDefaultAsync(t => t.Id == templateId);
if (template == null)
throw new InvalidOperationException($"Template with ID {templateId} not found.");
var now = baseDate ?? DateTime.Now;
var (year, month) = GetKeyDateParts(template, now);
var templateDate = await _dbContext.Set<NumberGeneratorTemplateDate>()
.FirstOrDefaultAsync(td => td.NumberGeneratorTemplateId == templateId && td.Year == year && td.Month == month);
if (templateDate == null)
{
templateDate = new NumberGeneratorTemplateDate
{
NumberGeneratorTemplateId = template.Id,
Year = year,
Month = month,
CurrentNumber = 0
};
_dbContext.Add(templateDate);
}
templateDate.CurrentNumber++;
var formatted = templateDate.CurrentNumber.ToString(template.DigitFormat);
var dynamicSuffix = BuildDynamicSuffix(template, now);
var result = BuildFormattedNumber(template, formatted, dynamicSuffix);
templateDate.LastGeneratedNumber = result;
await _dbContext.SaveChangesAsync();
return result;
}
catch
{
throw;
}
finally
{
semaphore.Release();
}
}
public async Task<string> GetSampleAsync(int templateId, DateTime? baseDate = null)
{
var template = await _dbContext.Set<NumberGeneratorTemplate>()
.AsNoTracking()
.FirstOrDefaultAsync(t => t.Id == templateId);
if (template == null)
throw new InvalidOperationException($"Template with ID {templateId} not found.");
var now = baseDate ?? DateTime.Now;
var formatted = 1.ToString(template.DigitFormat);
var dynamicSuffix = BuildDynamicSuffix(template, now);
return BuildFormattedNumber(template, formatted, dynamicSuffix);
}
public async Task<List<NumberGeneratorTemplateDTO>> GetAllNumbergeneratorsAsync()
{
var retVal = new List<NumberGeneratorTemplateDTO>();
try
{
var numbergenerators = await _dbContext.NumberGeneratorTemplates.ToListAsync();
foreach (var numbergenerator in numbergenerators)
{
var numbergeneratortemplateDTO = new NumberGeneratorTemplateDTO();
numbergeneratortemplateDTO.Id = numbergenerator.Id;
numbergeneratortemplateDTO.ShortName = numbergenerator.ShortName;
numbergeneratortemplateDTO.Sample = await this.GetSampleAsync(numbergenerator.Id, DateTime.Now);
retVal.Add(numbergeneratortemplateDTO);
}
}
catch (Exception ex)
{
Log.Error(ex.Message);
}
return retVal;
}
private SemaphoreSlim GetOrCreateSemaphore(int templateId)
{
lock (_templateLocks)
{
if (!_templateLocks.ContainsKey(templateId))
_templateLocks[templateId] = new SemaphoreSlim(1, 1);
return _templateLocks[templateId];
}
}
private static (int year, int? month) GetKeyDateParts(NumberGeneratorTemplate template, DateTime date)
{
int year = date.Year;
int? month = template.GenerateType == GenerateType.YearAndMonth ? date.Month : null;
return (year, month);
}
private static string BuildDynamicSuffix(NumberGeneratorTemplate template, DateTime date)
{
return template.GenerateType switch
{
GenerateType.OnlyYear => date.Year.ToString(),
GenerateType.YearAndMonth => $"{date.Year}/{date.Month:D2}",
_ => template.Suffix
};
}
private static string BuildFormattedNumber(NumberGeneratorTemplate template, string formattedNumber, string dynamicSuffix)
{
var sb = new StringBuilder();
if (!string.IsNullOrEmpty(template.Prefix))
sb.Append(template.Prefix);
if (!string.IsNullOrEmpty(template.PrefixSeparator) && !string.IsNullOrEmpty(template.Prefix))
sb.Append(template.PrefixSeparator);
sb.Append(formattedNumber);
if (!string.IsNullOrEmpty(dynamicSuffix))
{
if (!string.IsNullOrEmpty(template.SuffixSeparator))
sb.Append(template.SuffixSeparator);
sb.Append(dynamicSuffix);
}
return sb.ToString();
}
}
}