namespace MyOffice.Services.Currency; using AutoMapper; using Core; using Data.Models.Currencies; using Data.Repositories.Currency; using Domain; public class CurrencyService { private readonly ICurrencyGlobalRepository _currencyGlobalRepository; private readonly ICurrencyRepository _currencyRepository; private readonly ICurrencyRateRepository _currencyRateRepository; private readonly IMapper _mapper; public CurrencyService( ICurrencyGlobalRepository currencyGlobalRepository, ICurrencyRepository currencyRepository, ICurrencyRateRepository currencyRateRepository, IMapper mapper ) { _currencyGlobalRepository = currencyGlobalRepository; _currencyRepository = currencyRepository; _currencyRateRepository = currencyRateRepository; _mapper = mapper; } public async Task> GetGlobalAllAsync(CancellationToken cancellationToken = default) { return _mapper.Map>(await _currencyGlobalRepository.GetAllAsync(cancellationToken)); } public async Task> GetAllAsync(Guid userId, CancellationToken cancellationToken = default) { return _mapper.Map>(await _currencyRepository.GetAllAsync(userId, cancellationToken)); } public async Task> GetAllWithRatesAsync(Guid userId, CancellationToken cancellationToken = default) { var list = await _currencyRepository.GetAllAsync(userId, cancellationToken); var result = new List(list.Count); foreach (var currency in list) { var rates = await _currencyRateRepository.GetLastRatesAsync(currency.Id, cancellationToken: cancellationToken); result.Add(new CurrencyWithRateDto { Currency = _mapper.Map(currency), Rate = _mapper.Map(rates.FirstOrDefault()), }); } return result; } public async Task> CurrencyAddAsync( Guid userId, CurrencyDto input, CancellationToken cancellationToken = default) { if (input == null) throw new ArgumentNullException(nameof(input)); var result = new Exec(CurrencyAddStatus.success); var exists = await _currencyRepository.GetByGlobalCurrencyAsync(userId, input.CurrencyGlobalId, cancellationToken); if (exists != null) { return result.Set(_mapper.Map(exists), CurrencyAddStatus.exists); } var currency = new Currency { Id = Guid.NewGuid(), UserId = userId, CurrencyGlobalId = input.CurrencyGlobalId, Name = input.Name, ShortName = input.ShortName, }; if (!await _currencyRepository.AddAsync(currency, cancellationToken)) { return result.Set(CurrencyAddStatus.failed); } return result.Set(_mapper.Map(currency)); } public async Task> CurrencyUpdateAsync( Guid userId, Guid currencyId, CurrencyEdit currency, CancellationToken cancellationToken = default) { if (currency == null) throw new ArgumentNullException(nameof(currency)); var result = new Exec(CurrencyEditStatus.success); var exists = await _currencyRepository.GetAsync(userId, currencyId, cancellationToken); if (exists == null) { return result.Set(CurrencyEditStatus.not_found); } exists.Name = currency.Name; exists.ShortName = currency.ShortName; exists.IsPrimary = currency.IsPrimary; if (!await _currencyRepository.UpdateAsync(exists, cancellationToken)) { return result.Set(CurrencyEditStatus.failed); } if (exists.IsPrimary) { var primaries = await _currencyRepository.GetPrimariesAsync(userId, cancellationToken); foreach (var primary in primaries) { if (primary.Id != exists.Id) { primary.IsPrimary = false; await _currencyRepository.UpdateAsync(primary, cancellationToken); } } } return result.Set(_mapper.Map(exists)); } public async Task> CurrencyRateAddAsync( Guid userId, Guid currencyId, CurrencyRateDto input, CancellationToken cancellationToken = default) { if (input == null) throw new ArgumentNullException(nameof(input)); var result = new Exec(CurrencyAddRateStatus.success); var currency = await _currencyRepository.GetAsync(userId, currencyId, cancellationToken); if (currency == null) { return result.Set(CurrencyAddRateStatus.not_found); } var currencyRate = new CurrencyRate { CurrencyId = currency.Id, DateTime = input.DateTime.Date, Rate = input.Rate, Quantity = input.Quantity, }; var rates = await _currencyRateRepository.GetAtDateAsync(currencyRate.CurrencyId, currencyRate.DateTime, cancellationToken); var rate = rates.Find(x => x.Rate == currencyRate.Rate); if (rate == null) { if (!await _currencyRateRepository.AddRateAsync(currencyRate, cancellationToken)) { return result.Set(CurrencyAddRateStatus.failed); } // TODO: more logic to fix current rate if (currencyRate.DateTime.Date == DateTime.UtcNow.Date || !currency.CurrentRateId.HasValue) { currency.CurrencyGlobal = null; currency.CurrentRateId = currencyRate.Id; await _currencyRepository.UpdateAsync(currency, cancellationToken); } rate = currencyRate; } return result.Set(_mapper.Map(rate)); } public async Task> RemoveAsync( Guid userId, Guid id, CancellationToken cancellationToken = default) { var result = new Exec(GeneralExecStatus.success); var currency = await _currencyRepository.GetAsync(userId, id, cancellationToken); if (currency == null) { return result.Set(GeneralExecStatus.not_found); } if (!await _currencyRepository.RemoveAsync(currency, cancellationToken)) { return result.Set(GeneralExecStatus.failure); } return result.Set(_mapper.Map(currency)); } }