165 lines
6.0 KiB
C#
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();
|
|
}
|
|
}
|
|
|
|
|
|
}
|