Example #1
0
        /// <summary>
        /// Инициализира _numberIdDict и _externalIdDict и ги зарежда с идентификаторите на всички карти от БД
        /// </summary>
        /// <param name="serviceProvider">имплементация на IServiceProvider</param>
        /// <param name="cacheExpirationTimeout">време в секунди за което картите са налични в кеша</param>
        public void Init(IServiceProvider serviceProvider, int cacheExpirationTimeout, bool isSlidingExpiration)
        {
            try
            {
                _semaphoreSlim.Wait();
                //
                _numberIdDict           = new ConcurrentDictionary <string, string>();
                _externalIdDict         = new ConcurrentDictionary <string, string>();
                _cacheExpirationTimeout = cacheExpirationTimeout;
                _isSlidingExpiration    = isSlidingExpiration;

                ICardSystemRepository <Card> repo = serviceProvider.GetService <ICardSystemRepository <Card> >();
                ILogger logger     = new Logger();
                int     count      = repo.AsNoTracking().Count();
                int     step       = 40000;
                int     iterations = count / step;
                for (int i = 0; i <= iterations; i++)
                {
                    var cardIds = repo.AsNoTracking()
                                  .Select(c => new { c.Id, c.Number, c.ExternalId })
                                  .Skip(i * step)
                                  .Take(step)
                                  .AsEnumerable()
                                  .Select(c => (c.Id, c.Number, c.ExternalId))
                                  .ToArray();
                    foreach (var item in cardIds)
                    {
                        if (!string.IsNullOrWhiteSpace(item.Number) && !_numberIdDict.ContainsKey(item.Number))
                        {
                            _numberIdDict.AddOrUpdate(item.Number, item.Id, (oldNum, oldId) => item.Id);
                        }
                        if (!string.IsNullOrWhiteSpace(item.ExternalId) && !_externalIdDict.ContainsKey(item.ExternalId))
                        {
                            _externalIdDict.AddOrUpdate(item.ExternalId, item.Id, (oldNum, oldId) => item.Id);
                        }
                    }
                    logger.InfoLog($"Successfully load into card dictionaries mapping cache {cardIds.Length} cards");
                }
                // to do ...
            }
            finally
            {
                _semaphoreSlim.Release();
            }
        }
Example #2
0
        private Card GetByExternalId(IServiceProvider serviceProvider, string externalId)
        {
            Card entity = null;
            ICardSystemRepository <Card> repo = serviceProvider.GetService <ICardSystemRepository <Card> >();

            string cardId = CardCacheServiceV2.Instance.GetIdByExternalId(externalId);

            if (!string.IsNullOrWhiteSpace(cardId))
            {
                entity = CardCacheServiceV2.Instance.GetCard(serviceProvider, cardId);
                if (entity != null)
                {
                    return(entity);
                }
                entity = repo.AsNoTracking()
                         .Include(x => x.CardMode)
                         .Include(x => x.User)
                         .FirstOrDefault(x => x.Id == cardId);
                if (entity != null)
                {
                    CardCacheServiceV2.Instance.AddCard(serviceProvider, entity);
                    CardCacheServiceV2.Instance.AddNewMap(entity);
                }
                return(entity);
            }

            entity = repo.AsNoTracking()
                     .Include(x => x.CardMode)
                     .Include(x => x.User)
                     .FirstOrDefault(x => x.ExternalId == externalId);
            // add to cache
            if (entity != null)
            {
                CardCacheServiceV2.Instance.AddCard(serviceProvider, entity);
                CardCacheServiceV2.Instance.AddNewMap(entity);
            }
            return(entity);
        }
Example #3
0
        private Result <Card> UpdateCurrency(IServiceProvider serviceProvider, Card editedCard)
        {
            Result <Card> result = new Result <Card>();

            try
            {
                ICardSystemRepository <Card> repo = serviceProvider.GetService <ICardSystemRepository <Card> >();
                Card entity = repo.FirstOrDefault(x => x.Id == editedCard.Id);
                if (entity == null)
                {
                    _logger.LogException("BusinessServices.CanPlayService.UpdateCurrency => Entity not found!");
                    result.Messages.Add("Entity not found!");
                    result.IsSuccess = false;
                    return(result);
                }
                if (entity.ExternalId != editedCard.ExternalId)
                {
                    if (!IsExternalIdUnique(serviceProvider, editedCard.ExternalId, entity.Id))
                    {
                        _logger.LogException("BusinessServices.CanPlayService.UpdateCurrency => External ID is not UNIQUE!");
                        result.Messages.Add("External ID is not UNIQUE!");
                        result.IsSuccess = false;
                        return(result);
                    }
                }
                //Currency1
                entity.Currency1Balance      = editedCard.Currency1Balance;
                entity.Currency1BalanceBonus = editedCard.Currency1BalanceBonus;
                entity.Currency1Code         = editedCard.Currency1Code;
                entity.Currency1Name         = editedCard.Currency1Name;
                entity.Currency1TotalIncome  = editedCard.Currency1TotalIncome;
                entity.Currency1TotalSpend   = editedCard.Currency1TotalSpend;
                //CurrencyBonus
                entity.CurrencyBonusBalance      = editedCard.CurrencyBonusBalance;
                entity.CurrencyBonusBalanceBonus = editedCard.CurrencyBonusBalanceBonus;
                entity.CurrencyBonusCode         = editedCard.CurrencyBonusCode;
                entity.CurrencyBonusName         = editedCard.CurrencyBonusName;
                entity.CurrencyBonusTotalIncome  = editedCard.CurrencyBonusTotalIncome;
                entity.CurrencyBonusTotalSpend   = editedCard.CurrencyBonusTotalSpend;
                //CurrencyCredit
                entity.CurrencyCreditBalance      = editedCard.CurrencyCreditBalance;
                entity.CurrencyCreditBalanceBonus = editedCard.CurrencyCreditBalanceBonus;
                entity.CurrencyCreditCode         = editedCard.CurrencyCreditCode;
                entity.CurrencyCreditName         = editedCard.CurrencyCreditName;
                entity.CurrencyCreditTotalIncome  = editedCard.CurrencyCreditTotalIncome;
                entity.CurrencyCreditTotalSpend   = editedCard.CurrencyCreditTotalSpend;
                //CurrencyPrimary
                entity.CurrencyPrimaryBalance      = editedCard.CurrencyPrimaryBalance;
                entity.CurrencyPrimaryBalanceBonus = editedCard.CurrencyPrimaryBalanceBonus;
                entity.CurrencyPrimaryCode         = editedCard.CurrencyPrimaryCode;
                entity.CurrencyPrimaryName         = editedCard.CurrencyPrimaryName;
                entity.CurrencyPrimaryTotalIncome  = editedCard.CurrencyPrimaryTotalIncome;
                entity.CurrencyPrimaryTotalSpend   = editedCard.CurrencyPrimaryTotalSpend;
                //CurrencyTicket
                entity.CurrencyTicketBalance      = editedCard.CurrencyTicketBalance;
                entity.CurrencyTicketBalanceBonus = editedCard.CurrencyTicketBalanceBonus;
                entity.CurrencyTicketCode         = editedCard.CurrencyTicketCode;
                entity.CurrencyTicketName         = editedCard.CurrencyTicketName;
                entity.CurrencyTicketTotalIncome  = editedCard.CurrencyTicketTotalIncome;
                entity.CurrencyTicketTotalSpend   = editedCard.CurrencyTicketTotalSpend;
                //CurrencyTime
                entity.CurrencyTimeBalance      = editedCard.CurrencyTimeBalance;
                entity.CurrencyTimeBalanceBonus = editedCard.CurrencyTimeBalanceBonus;
                entity.CurrencyTimeCode         = editedCard.CurrencyTimeCode;
                entity.CurrencyTimeName         = editedCard.CurrencyTimeName;
                entity.CurrencyTimeTotalIncome  = editedCard.CurrencyTimeTotalIncome;
                entity.CurrencyTimeTotalSpend   = editedCard.CurrencyTimeTotalSpend;

                entity.FreePeriod          = editedCard.FreePeriod;
                entity.FreePeriodStart     = editedCard.FreePeriodStart;
                entity.FreePeriodEnd       = editedCard.FreePeriodEnd;
                entity.LastTransactionTime = DateTime.UtcNow;
                repo.Update();

                // update cache
                Card cachedEntity = CardCacheServiceV2.Instance.GetCard(serviceProvider, entity.Id);
                if (cachedEntity != null)
                {
                    //Currency1
                    cachedEntity.Currency1Balance      = entity.Currency1Balance;
                    cachedEntity.Currency1BalanceBonus = entity.Currency1BalanceBonus;
                    cachedEntity.Currency1Code         = entity.Currency1Code;
                    cachedEntity.Currency1Name         = entity.Currency1Name;
                    cachedEntity.Currency1TotalIncome  = entity.Currency1TotalIncome;
                    cachedEntity.Currency1TotalSpend   = entity.Currency1TotalSpend;
                    //CurrencyBonus
                    cachedEntity.CurrencyBonusBalance      = entity.CurrencyBonusBalance;
                    cachedEntity.CurrencyBonusBalanceBonus = entity.CurrencyBonusBalanceBonus;
                    cachedEntity.CurrencyBonusCode         = entity.CurrencyBonusCode;
                    cachedEntity.CurrencyBonusName         = entity.CurrencyBonusName;
                    cachedEntity.CurrencyBonusTotalIncome  = entity.CurrencyBonusTotalIncome;
                    cachedEntity.CurrencyBonusTotalSpend   = entity.CurrencyBonusTotalSpend;
                    //CurrencyCredit
                    cachedEntity.CurrencyCreditBalance      = entity.CurrencyCreditBalance;
                    cachedEntity.CurrencyCreditBalanceBonus = entity.CurrencyCreditBalanceBonus;
                    cachedEntity.CurrencyCreditCode         = entity.CurrencyCreditCode;
                    cachedEntity.CurrencyCreditName         = entity.CurrencyCreditName;
                    cachedEntity.CurrencyCreditTotalIncome  = entity.CurrencyCreditTotalIncome;
                    cachedEntity.CurrencyCreditTotalSpend   = entity.CurrencyCreditTotalSpend;
                    //CurrencyPrimary
                    cachedEntity.CurrencyPrimaryBalance      = entity.CurrencyPrimaryBalance;
                    cachedEntity.CurrencyPrimaryBalanceBonus = entity.CurrencyPrimaryBalanceBonus;
                    cachedEntity.CurrencyPrimaryCode         = entity.CurrencyPrimaryCode;
                    cachedEntity.CurrencyPrimaryName         = entity.CurrencyPrimaryName;
                    cachedEntity.CurrencyPrimaryTotalIncome  = entity.CurrencyPrimaryTotalIncome;
                    cachedEntity.CurrencyPrimaryTotalSpend   = entity.CurrencyPrimaryTotalSpend;
                    //CurrencyTicket
                    cachedEntity.CurrencyTicketBalance      = entity.CurrencyTicketBalance;
                    cachedEntity.CurrencyTicketBalanceBonus = entity.CurrencyTicketBalanceBonus;
                    cachedEntity.CurrencyTicketCode         = entity.CurrencyTicketCode;
                    cachedEntity.CurrencyTicketName         = entity.CurrencyTicketName;
                    cachedEntity.CurrencyTicketTotalIncome  = entity.CurrencyTicketTotalIncome;
                    cachedEntity.CurrencyTicketTotalSpend   = entity.CurrencyTicketTotalSpend;
                    //CurrencyTime
                    cachedEntity.CurrencyTimeBalance      = entity.CurrencyTimeBalance;
                    cachedEntity.CurrencyTimeBalanceBonus = entity.CurrencyTimeBalanceBonus;
                    cachedEntity.CurrencyTimeCode         = entity.CurrencyTimeCode;
                    cachedEntity.CurrencyTimeName         = entity.CurrencyTimeName;
                    cachedEntity.CurrencyTimeTotalIncome  = entity.CurrencyTimeTotalIncome;
                    cachedEntity.CurrencyTimeTotalSpend   = entity.CurrencyTimeTotalSpend;

                    cachedEntity.FreePeriod          = entity.FreePeriod;
                    cachedEntity.FreePeriodStart     = entity.FreePeriodStart;
                    cachedEntity.FreePeriodEnd       = entity.FreePeriodEnd;
                    cachedEntity.LastTransactionTime = entity.LastTransactionTime;
                    CardCacheServiceV2.Instance.AddCard(serviceProvider, cachedEntity);
                    CardCacheServiceV2.Instance.AddNewMap(cachedEntity);
                }

                result.Data      = entity;
                result.IsSuccess = true;

                return(result);
            }
            catch (Exception ex)
            {
                _logger.LogException($"BusinessServices.CanPlayService.UpdateCurrency throws: {ex.Message}");
                result.Messages.Add($"Cannot edit card currencies! Something went wrong. {ex.Message}");
                result.IsSuccess = false;

                return(result);
            }
        }
Example #4
0
        private (bool success, ServicePriceResponse response) ServicePriceInternal(
            Guid guid,
            string concentratorId,
            string controllerId,
            int cardType,
            string cardId,
            string serviceId,
            int transactionId,
            int endpointRssi,
            int concentratorRssi)
        {
            Concentrator getConcentrator()
            {
                var repo = _serviceProvider.GetService <ICardSystemRepository <Concentrator> >();

                return(repo.AsNoTracking().FirstOrDefault(x => x.DeviceId == concentratorId));
            };
            ControllerConfigRelay getController()
            {
                var repo = _serviceProvider.GetService <ICardSystemRepository <ControllerConfigRelay> >();

                return(repo.AsNoTracking()
                       .Include(x => x.EGM)
                       .ThenInclude(x => x.AllowedCurrencies)
                       .FirstOrDefault(x => x.SerialNumber == controllerId && x.OwnerId == _ownerId));
            };
            Card getCard()
            {
                Card entity = null;
                ICardSystemRepository <Card> repo = null;
                string cardDBId = CardCacheServiceV2.Instance.GetIdByExternalId(cardId);

                if (!string.IsNullOrWhiteSpace(cardDBId))
                {
                    entity = CardCacheServiceV2.Instance.GetCard(_serviceProvider, cardDBId);
                    if (entity != null)
                    {
                        return(entity);
                    }
                    repo   = _serviceProvider.GetService <ICardSystemRepository <Card> >();
                    entity = repo.AsNoTracking()
                             .Include(x => x.CardMode)
                             .Include(x => x.User)
                             .FirstOrDefault(x => x.Id == cardDBId);
                    if (entity != null)
                    {
                        CardCacheServiceV2.Instance.AddCard(_serviceProvider, entity);
                        CardCacheServiceV2.Instance.AddNewMap(entity);
                    }
                    return(entity);
                }

                repo   = _serviceProvider.GetService <ICardSystemRepository <Card> >();
                entity = repo.AsNoTracking()
                         .Include(x => x.CardMode)
                         .Include(x => x.User)
                         .FirstOrDefault(x => x.ExternalId == cardId);
                if (entity != null)
                {
                    CardCacheServiceV2.Instance.AddCard(_serviceProvider, entity);
                    CardCacheServiceV2.Instance.AddNewMap(entity);
                }
                return(entity);
            };
            EGM getEGM()
            {
                var repo = _serviceProvider.GetService <ICardSystemRepository <EGM> >();

                return(repo.AsNoTracking()
                       .Include(x => x.AllowedCurrencies)
                       .Include(x => x.ConfigRelays)
                       .Include(x => x.GameCategory)
                       .Include(x => x.GameManageControllers)
                       .Include(x => x.Images)
                       .Include(x => x.LightingEvent)
                       .Include(x => x.LightingSignals)
                       .Include(x => x.ScheduleDays)
                       .FirstOrDefault(x => x.Id == serviceId));
            }

            var concentrator = getConcentrator();

            if (concentrator == null)
            {
                var response = new ServicePriceResponse
                {
                    TransactionId  = transactionId,
                    Time           = DateTime.UtcNow,
                    ResponseCode   = 101,
                    ConcentratorId = concentratorId,
                    ControllerId   = controllerId,
                    CardType       = cardType,
                    CardId         = cardId,
                    CardNumber     = string.Empty,
                    ServiceId      = string.Empty,
                    ServiceName    = string.Empty,
                    Price          = 0
                };
                _logger.ErrorLog($"[CardService.ServicePriceInternal][-OUT-] [{guid}] TransactionId {transactionId} | ConcentratorId {concentratorId} | ControllerId {controllerId} | CardType {cardType} | CardId {cardId} | ServiceId {serviceId} | EndpointRssi: {endpointRssi} | ConcentratorRssi {concentratorRssi} | {JsonSerializer.Serialize(response, new JsonSerializerOptions { WriteIndented = false })}", GetIpAddress());
                return(false, response);
            }
            var controller = getController();

            if (controller == null)
            {
                var response = new ServicePriceResponse
                {
                    TransactionId  = transactionId,
                    Time           = DateTime.UtcNow,
                    ResponseCode   = 102,
                    ConcentratorId = concentratorId,
                    ControllerId   = controllerId,
                    CardType       = cardType,
                    CardId         = cardId,
                    CardNumber     = string.Empty,
                    ServiceId      = string.Empty,
                    ServiceName    = string.Empty,
                    Price          = 0
                };
                _logger.ErrorLog($"[CardService.ServicePriceInternal][-OUT-] [{guid}] TransactionId {transactionId} | ConcentratorId {concentratorId} | ControllerId {controllerId} | CardType {cardType} | CardId {cardId} | ServiceId {serviceId} | EndpointRssi: {endpointRssi} | ConcentratorRssi {concentratorRssi} | {JsonSerializer.Serialize(response, new JsonSerializerOptions { WriteIndented = false })}", GetIpAddress());
                return(false, response);
            }
            var card = getCard();

            if (card == null)
            {
                var response = new ServicePriceResponse
                {
                    TransactionId  = transactionId,
                    Time           = DateTime.UtcNow,
                    ResponseCode   = 103,
                    ConcentratorId = concentratorId,
                    ControllerId   = controllerId,
                    CardType       = cardType,
                    CardId         = cardId,
                    CardNumber     = string.Empty,
                    ServiceId      = string.Empty,
                    ServiceName    = string.Empty,
                    Price          = 0
                };
                _logger.ErrorLog($"[CardService.ServicePriceInternal][-OUT-] [{guid}] TransactionId {transactionId} | ConcentratorId {concentratorId} | ControllerId {controllerId} | CardType {cardType} | CardId {cardId} | ServiceId {serviceId} | EndpointRssi: {endpointRssi} | ConcentratorRssi {concentratorRssi} | {JsonSerializer.Serialize(response, new JsonSerializerOptions { WriteIndented = false })}", GetIpAddress());
                return(false, response);
            }
            var egm = getEGM();

            if (egm == null)
            {
                var response = new ServicePriceResponse
                {
                    TransactionId  = transactionId,
                    Time           = DateTime.UtcNow,
                    ResponseCode   = 132,
                    ConcentratorId = concentratorId,
                    ControllerId   = controllerId,
                    CardType       = cardType,
                    CardId         = cardId,
                    CardNumber     = string.Empty,
                    ServiceId      = string.Empty,
                    ServiceName    = string.Empty,
                    Price          = 0
                };
                _logger.ErrorLog($"[CardService.ServicePriceInternal][-OUT-] [{guid}] TransactionId {transactionId} | ConcentratorId {concentratorId} | ControllerId {controllerId} | CardType {cardType} | CardId {cardId} | ServiceId {serviceId} | EndpointRssi: {endpointRssi} | ConcentratorRssi {concentratorRssi} | {JsonSerializer.Serialize(response, new JsonSerializerOptions { WriteIndented = false })}", GetIpAddress());
                return(false, response);
            }

            IEnumerable <ScheduleDay> getScheduleDays()
            {
                IEnumerable <ScheduleDay> egmPriceModifiers = null;
                var repo = _serviceProvider.GetService <ICardSystemRepository <ScheduleDay> >();

                if (!string.IsNullOrWhiteSpace(controller.EGM.Id))
                {
                    egmPriceModifiers = repo.AsNoTracking()
                                        .Include(x => x.Hours)
                                        .Where(x => x.EGMId == controller.EGM.Id)
                                        .AsEnumerable();
                }
                if (egmPriceModifiers != null && !egmPriceModifiers.Any())
                {
                    egmPriceModifiers = repo
                                        .AsNoTracking()
                                        .Include(x => x.Hours)
                                        .Where(x => x.GameCenterId == controller.EGM.GameCenterId)
                                        .AsEnumerable();
                }
                return(egmPriceModifiers ?? new List <ScheduleDay>());
            }

            var scheduleDays = getScheduleDays();

            decimal price = _serviceProvider.GetService <ICanPlayService>().GetPricePerGame(
                _serviceProvider,
                scheduleDays.ToList(),
                egm);

            ServicePriceResponse servicePriceResponse = new ServicePriceResponse
            {
                TransactionId  = transactionId,
                Time           = DateTime.UtcNow,
                ResponseCode   = 0,
                ConcentratorId = concentrator.DeviceId,
                ControllerId   = controller.SerialNumber,
                CardType       = card.Type,
                CardId         = card.ExternalId,
                CardNumber     = card.Number,
                ServiceId      = egm.Id,
                ServiceName    = egm.MachineName,
                Price          = (double)price
            };

            _logger.InfoLog($"[CardService.ServicePriceInternal][-OUT-] [{guid}] TransactionId {transactionId} | ConcentratorId {concentratorId} | ControllerId {controllerId} | CardType {cardType} | CardId {cardId} | ServiceId {serviceId} | EndpointRssi: {endpointRssi} | ConcentratorRssi {concentratorRssi} | DB Result {JsonSerializer.Serialize(servicePriceResponse, new JsonSerializerOptions { WriteIndented = false })}", GetIpAddress());
            return(true, servicePriceResponse);
        }
Example #5
0
        private async ValueTask <(bool success, CanPlayResponse response)> CanPlayAsyncInternal(
            Guid guid,
            string concentratorId,
            string controllerId,
            int cardType,
            string cardId,
            bool shouldPay,
            int transactionId,
            int endpointRssi,
            int concentratorRssi)
        {
            Concentrator getConcentrator()
            {
                var repo = _serviceProvider.GetService <ICardSystemRepository <Concentrator> >();

                return(repo.AsNoTracking().FirstOrDefault(x => x.DeviceId == concentratorId));
            };
            ControllerConfigRelay getController()
            {
                var repo = _serviceProvider.GetService <ICardSystemRepository <ControllerConfigRelay> >();

                return(repo.AsNoTracking()
                       .Include(x => x.EGM)
                       .ThenInclude(x => x.AllowedCurrencies)
                       .FirstOrDefault(x => x.SerialNumber == controllerId && x.OwnerId == _ownerId));
            };
            Card getCard()
            {
                Card entity = null;
                ICardSystemRepository <Card> repo = null;
                string cardDBId = CardCacheServiceV2.Instance.GetIdByExternalId(cardId);

                if (!string.IsNullOrWhiteSpace(cardDBId))
                {
                    entity = CardCacheServiceV2.Instance.GetCard(_serviceProvider, cardDBId);
                    if (entity != null)
                    {
                        return(entity);
                    }
                    repo   = _serviceProvider.GetService <ICardSystemRepository <Card> >();
                    entity = repo.AsNoTracking()
                             .Include(x => x.CardMode)
                             .Include(x => x.User)
                             .FirstOrDefault(x => x.Id == cardDBId);
                    if (entity != null)
                    {
                        CardCacheServiceV2.Instance.AddCard(_serviceProvider, entity);
                        CardCacheServiceV2.Instance.AddNewMap(entity);
                    }
                    return(entity);
                }

                repo   = _serviceProvider.GetService <ICardSystemRepository <Card> >();
                entity = repo.AsNoTracking()
                         .Include(x => x.CardMode)
                         .Include(x => x.User)
                         .FirstOrDefault(x => x.ExternalId == cardId);
                if (entity != null)
                {
                    CardCacheServiceV2.Instance.AddCard(_serviceProvider, entity);
                    CardCacheServiceV2.Instance.AddNewMap(entity);
                }
                return(entity);
            };
            IEnumerable <CurrencyTemplate> getCurrencyTemplates()
            {
                var repo = _serviceProvider.GetService <ICardSystemRepository <CurrencyTemplate> >();

                return(repo.AsNoTracking()
                       .Where(x => x.OwnerId == _ownerId)
                       .ToList());
            }

            var concentrator = getConcentrator();

            if (concentrator == null)
            {
                var response = new CanPlayResponse
                {
                    TransactionId    = transactionId,
                    Time             = DateTime.UtcNow,
                    ResponseCode     = 101,
                    ConcentratorId   = concentratorId,
                    ControllerId     = controllerId,
                    CardType         = cardType,
                    CardId           = cardId,
                    CardNumber       = string.Empty,
                    ServiceId        = string.Empty,
                    ServiceName      = string.Empty,
                    Permission       = false,
                    RelayType        = string.Empty,
                    RelayPulse       = 0,
                    RelayOnTime      = 0,
                    RelayOffTime     = 0,
                    RelayDisplayTime = 0,
                    DisplayLine1     = "Err 101",
                    DisplayLine2     = "Concentrator N/A"
                };
                _logger.ErrorLog($"[CardService.CanPlayAsyncInternal][-OUT-] [{guid}] TransactionId {transactionId} | ConcentratorId {concentratorId} | ControllerId {controllerId} | CardType {cardType} | CardId {cardId} | ShouldPay {shouldPay} | EndpointRssi: {endpointRssi} | ConcentratorRssi {concentratorRssi} | {JsonSerializer.Serialize(response, new JsonSerializerOptions { WriteIndented = false })}", GetIpAddress());
                return(false, response);
            }
            var controller = getController();

            if (controller == null)
            {
                var response = new CanPlayResponse
                {
                    TransactionId    = transactionId,
                    Time             = DateTime.UtcNow,
                    ResponseCode     = 102,
                    ConcentratorId   = concentratorId,
                    ControllerId     = controllerId,
                    CardType         = cardType,
                    CardId           = cardId,
                    CardNumber       = string.Empty,
                    ServiceId        = string.Empty,
                    ServiceName      = string.Empty,
                    Permission       = false,
                    RelayType        = string.Empty,
                    RelayPulse       = 0,
                    RelayOnTime      = 0,
                    RelayOffTime     = 0,
                    RelayDisplayTime = 0,
                    DisplayLine1     = "Err 102",
                    DisplayLine2     = "Controller N/A"
                };
                _logger.ErrorLog($"[CardService.CanPlayAsyncInternal][-OUT-] [{guid}] TransactionId {transactionId} | ConcentratorId {concentratorId} | ControllerId {controllerId} | CardType {cardType} | CardId {cardId} | ShouldPay {shouldPay} | EndpointRssi: {endpointRssi} | ConcentratorRssi {concentratorRssi} | {JsonSerializer.Serialize(response, new JsonSerializerOptions { WriteIndented = false })}", GetIpAddress());
                return(false, response);
            }
            var card = getCard();

            if (card == null)
            {
                var response = new CanPlayResponse
                {
                    TransactionId    = transactionId,
                    Time             = DateTime.UtcNow,
                    ResponseCode     = 103,
                    ConcentratorId   = concentratorId,
                    ControllerId     = controllerId,
                    CardType         = cardType,
                    CardId           = cardId,
                    CardNumber       = string.Empty,
                    ServiceId        = string.Empty,
                    ServiceName      = string.Empty,
                    Permission       = false,
                    RelayType        = string.Empty,
                    RelayPulse       = 0,
                    RelayOnTime      = 0,
                    RelayOffTime     = 0,
                    RelayDisplayTime = 0,
                    DisplayLine1     = "Err 103",
                    DisplayLine2     = "Card N/A"
                };
                _logger.ErrorLog($"[CardService.CanPlayAsyncInternal][-OUT-] [{guid}] TransactionId {transactionId} | ConcentratorId {concentratorId} | ControllerId {controllerId} | CardType {cardType} | CardId {cardId} | ShouldPay {shouldPay} | EndpointRssi: {endpointRssi} | ConcentratorRssi {concentratorRssi} | {JsonSerializer.Serialize(response, new JsonSerializerOptions { WriteIndented = false })}", GetIpAddress());
                return(false, response);
            }
            var currencyTemplates = getCurrencyTemplates();

            IEnumerable <ScheduleDay> getScheduleDays()
            {
                IEnumerable <ScheduleDay> egmPriceModifiers = null;
                var repo = _serviceProvider.GetService <ICardSystemRepository <ScheduleDay> >();

                if (!string.IsNullOrWhiteSpace(controller.EGM.Id))
                {
                    egmPriceModifiers = repo.AsNoTracking()
                                        .Include(x => x.Hours)
                                        .Where(x => x.EGMId == controller.EGM.Id)
                                        .AsEnumerable();
                }
                if (egmPriceModifiers != null && !egmPriceModifiers.Any())
                {
                    egmPriceModifiers = repo
                                        .AsNoTracking()
                                        .Include(x => x.Hours)
                                        .Where(x => x.GameCenterId == controller.EGM.GameCenterId)
                                        .AsEnumerable();
                }
                return(egmPriceModifiers ?? new List <ScheduleDay>());
            }

            var scheduleDays = getScheduleDays();

            // ако се изиква плащане този метод променя баланса на картата
            var canPlayDto = _serviceProvider.GetService <ICanPlayService>().CanPlayV2(
                _serviceProvider,
                concentrator,
                controller,
                card,
                scheduleDays.ToList(),
                shouldPay,
                currencyTemplates);

            if (canPlayDto.HasError)
            {
                var errors   = canPlayDto.Message.Split('|');
                var response = new CanPlayResponse
                {
                    TransactionId    = transactionId,
                    Time             = DateTime.UtcNow,
                    ResponseCode     = int.Parse(errors[0]),
                    ConcentratorId   = concentratorId,
                    ControllerId     = controllerId,
                    CardType         = cardType,
                    CardId           = cardId,
                    CardNumber       = string.Empty,
                    ServiceId        = string.Empty,
                    ServiceName      = string.Empty,
                    Permission       = false,
                    RelayType        = string.Empty,
                    RelayPulse       = 0,
                    RelayOnTime      = 0,
                    RelayOffTime     = 0,
                    RelayDisplayTime = 0,
                    DisplayLine1     = $"Err {errors[0]}",
                    DisplayLine2     = errors[1]
                };
                _logger.ErrorLog($"[CardService.CanPlayAsyncInternal][-OUT-] [{guid}] TransactionId {transactionId} | ConcentratorId {concentratorId} | ControllerId {controllerId} | CardType {cardType} | CardId {cardId} | ShouldPay {shouldPay} | EndpointRssi: {endpointRssi} | ConcentratorRssi {concentratorRssi} | {JsonSerializer.Serialize(response, new JsonSerializerOptions { WriteIndented = false })}", GetIpAddress());
                return(false, response);
            }

            EGM gameDto = null;

            if (canPlayDto.CanPlay)
            {
                gameDto = controller.EGM;
            }

            var canPlayResponse = new CanPlayResponse
            {
                TransactionId    = transactionId,
                Time             = DateTime.UtcNow,
                ResponseCode     = 0,
                ConcentratorId   = concentrator.DeviceId,
                ControllerId     = controller.SerialNumber,
                CardType         = card.Type,
                CardId           = card.ExternalId,
                CardNumber       = card.Number,
                ServiceId        = canPlayDto.GameId,
                ServiceName      = canPlayDto.GameName,
                Permission       = canPlayDto.CanPlay,
                RelayType        = gameDto?.RelayMode,
                RelayPulse       = gameDto?.RelayPulse ?? 0,
                RelayOnTime      = gameDto?.RelayOnTime ?? 0,
                RelayOffTime     = gameDto?.RelayOffTime ?? 0,
                RelayDisplayTime = gameDto?.RelayDisplayTime ?? 0,
                DisplayLine1     = $"{canPlayDto.PricePerGame:F2}".Trim().Trim(',').Trim(),
                DisplayLine2     = $"{canPlayDto.RemainingBalance:F2}"
            };

            // само ако се изисква плащане логира плащането в транзакшън лога и обновява кеша на картата в api.icardmanager.eu
            if (shouldPay)
            {
                canPlayDto.GameId = gameDto?.Id;
                string relayInfo = $" | Relay ontime: {gameDto?.RelayOnTime}, Relay offtime: {gameDto?.RelayOffTime}, Relay pulse: {gameDto?.RelayPulse}, Relay display time: {gameDto?.RelayDisplayTime}, Relay mode: {gameDto?.RelayMode}, Game Serial Number: '{gameDto?.SerialNumber}'";
                CreateCanPlayLog(
                    concentrator.DeviceId,
                    controller.SerialNumber,
                    $"{canPlayDto.GameCenterName}{relayInfo}",
                    canPlayDto.GameId,
                    canPlayDto.GameName,
                    canPlayDto.CurrencyInfo,
                    card.ExternalId,
                    card.Type,
                    canPlayDto.PricePerGame,
                    canPlayDto.PaidFromBonusBalance,
                    canPlayDto.CanPlay,
                    gameDto?.GameCenterId,
                    gameDto != null ? gameDto.OwnerId : "system"
                    );
                try
                {
                    var apiResponse = await _restApiClient.GetAsync <string>(_configuration.GetSection("AppSettings:ApiServiceURL").Get <string>(), $"api/{_ownerId}/card/{card.Id}/reloadcache");

                    if (apiResponse.hasError)
                    {
                        _logger.ErrorLog($"[CardService.CanPlayAsyncInternal][-API-] [{guid}] TransactionId {transactionId} | ConcentratorId {concentratorId} | ControllerId {controllerId} | CardType {cardType} | CardId {cardId} | ShouldPay {shouldPay} | EndpointRssi: {endpointRssi} | ConcentratorRssi {concentratorRssi} | {apiResponse.errorMessage}", GetIpAddress());
                    }
                }
                catch (Exception ex)
                {
                    _logger.LogException($"CardService.CanPlayAsyncInternal throws: {ex}");
                }
            }

            _logger.InfoLog($"[CardService.CanPlayAsyncInternal][-OUT-] [{guid}] TransactionId {transactionId} | ConcentratorId {concentratorId} | ControllerId {controllerId} | CardType {cardType} | CardId {cardId} | ShouldPay {shouldPay} | EndpointRssi: {endpointRssi} | ConcentratorRssi {concentratorRssi} | DB Result {JsonSerializer.Serialize(canPlayResponse, new JsonSerializerOptions { WriteIndented = false })}", GetIpAddress());
            return(true, canPlayResponse);
        }