public async Task Create(DonorContext db, IIntegrationEventQueue queue, bool commitTransaction = true)
        {
            if (!IsValidated)
            {
                throw new Exception("Please validate model before creation.");
            }

            var donor = await db.Donors.FilterDeletedItems().SingleOrDefaultAsync(x => x.Id == DonorId);

            if (donor == null)
            {
                throw new ArgumentException($"Donor with ID '{DonorId}' does not exist.", nameof(DonorId));
            }

            var transactionSource = new TransactionSource();

            MapToEntity(transactionSource);
            db.TransactionSources.Add(transactionSource);
            MapFromEntity(transactionSource);

            if (commitTransaction)
            {
                await db.SaveChangesAsync();

                Id = transactionSource.Id;
                var integrationEvent = new IntegrationEvent <DonorTransactionSourceEvent>(ServiceNames.DonorService.ToString(), EventNames.AddDonorTransactionSource.ToString(), ToDonorTransactionSourceEvent());
                queue.Post(integrationEvent);
            }
        }
        public async Task Create(CharityContext db, IIntegrationEventQueue queue, IRequestContext requestContext)
        {
            if (!IsValidated)
            {
                throw new Exception("Please validate model before creation.");
            }

            var donor = new Charity();

            MapToEntity(donor, requestContext);
            db.Charities.Add(donor);
            await db.SaveChangesAsync();

            Id = donor.Id;

            var integrationEvent = new IntegrationEvent <CharityEvent>(ServiceNames.CharityService.ToString(), EventNames.AddCharity.ToString(), ToCharityEvent());

            queue.Post(integrationEvent);
        }
        public async Task Remove(CharityContext db, IIntegrationEventQueue queue)
        {
            if (!Id.HasValue)
            {
                throw new Exception("Please ensure that Id field has been populated before removing.");
            }
            var charity = await db.Charities.FilterDeletedItems().SingleOrDefaultAsync(x => x.Id == Id);

            if (charity == null)
            {
                throw new ArgumentException($"Donor with ID '{Id}' does not exist.", nameof(Id));
            }

            charity.IsDeleted = true;
            MapFromEntity(charity);
            await db.SaveChangesAsync();

            var integrationEvent = new IntegrationEvent <CharityEvent>(ServiceNames.CharityService.ToString(), EventNames.RemoveCharity.ToString(), ToCharityEvent());

            queue.Post(integrationEvent);
        }
        public async Task Remove(DonorContext db, IIntegrationEventQueue queue)
        {
            if (!Id.HasValue)
            {
                throw new Exception("Please ensure that Id field has been populated before removing.");
            }
            var transactionSource = await db.TransactionSources.FilterDeletedItems().SingleOrDefaultAsync(x => x.Id == Id);

            if (transactionSource == null)
            {
                throw new ArgumentException($"Transaction Source with ID '{Id}' does not exist.", nameof(Id));
            }

            transactionSource.IsDeleted = true;
            MapFromEntity(transactionSource);
            await db.SaveChangesAsync();

            var integrationEvent = new IntegrationEvent <DonorTransactionSourceEvent>(ServiceNames.DonorService.ToString(), EventNames.RemoveDonorTransactionSource.ToString(), ToDonorTransactionSourceEvent());

            queue.Post(integrationEvent);
        }
        protected override async Task ProcessEvent(TransactionEvent @event)
        {
            if (HasProcessedTransaction(@event))
            {
                return;
            }

            var donorTransactionSource = GetDonorTransactionSource(@event);

            if (donorTransactionSource == null)
            {
                return;
            }

            var merchant = GetOrCreateMerchant(@event);

            var transaction = new Transaction
            {
                Amount   = @event.Amount,
                Currency = @event.Currency,
                ExternalTransactionIdentifier = @event.TransactionIdentifier,
                ReceivedDateTimeUtc           = DateTime.UtcNow,
                TransactionDateTimeUtc        = @event.TransactionDateTimeUtc,
                TransactionIdentifier         = Guid.NewGuid(),
                Merchant                 = merchant,
                MerchantId               = merchant.Id,
                DonorTransactionSource   = donorTransactionSource,
                DonorTransactionSourceId = donorTransactionSource.Id
            };

            _fundContext.Transactions.Add(transaction);
            await _fundContext.SaveChangesAsync();

            var transactionIntegrationEvent = ToTransactionIntegrationEvent(transaction);
            var integrationEvent            = new IntegrationEvent <TransactionIntegrationEvent>(ServiceNames.TransactionProcessor.ToString(), EventNames.NewTransaction.ToString(), transactionIntegrationEvent);

            _queue.Post(integrationEvent);
        }
        public async Task Update(CharityContext db, IIntegrationEventQueue queue, IRequestContext requestContext)
        {
            if (!IsValidated)
            {
                throw new Exception("Please validate model before creation.");
            }

            var charity = await db.Charities.FilterDeletedItems().SingleOrDefaultAsync(x => x.Id == Id);

            if (charity == null)
            {
                throw new ArgumentException($"Donor with ID '{Id}' does not exist.", nameof(Id));
            }

            MapToEntity(charity, requestContext);
            await db.SaveChangesAsync();

            MapFromEntity(charity);

            var integrationEvent = new IntegrationEvent <CharityEvent>(ServiceNames.CharityService.ToString(), EventNames.UpdateCharity.ToString(), ToCharityEvent());

            queue.Post(integrationEvent);
        }
        private void SendTransaction(object obj)
        {
            _logger.Info("Sending transaction...");

            var donorTransactionSources = _db.DonorTransactionSources
                                          .FilterDeletedItems()
                                          .ToList();

            var random = new Random(Guid.NewGuid().GetHashCode());

            foreach (var ts in donorTransactionSources)
            {
                var merchantIndex = random.Next(0, 10);
                var merchant      = _merchants.ElementAt(merchantIndex);

                var transactionEvent = new TransactionEvent
                {
                    Amount                      = random.Next(1, 10000),
                    Currency                    = "ZAR",
                    MerchantIdentifier          = merchant.Key.ToString(),
                    MerchantName                = merchant.Value,
                    TransactionDateTimeUtc      = DateTime.UtcNow,
                    TransactionIdentifier       = Guid.NewGuid().ToString(),
                    TransactionSourceIdentifier = ts.Identifier
                };

                var integrationEvent = new IntegrationEvent <TransactionEvent>
                {
                    Body        = transactionEvent,
                    DateTimeUtc = DateTime.UtcNow,
                    Event       = EventNames.NewTransaction.ToString(),
                    Service     = ServiceNames.TransactionFeed.ToString()
                };

                _transactionFeedService.Post(integrationEvent);
            }
        }