/// <summary>
        /// Record that quiz has been completed.  Mark Citation as Closed.
        /// </summary>
        /// <param name="payload"></param>
        /// <returns></returns>
        public async Task CompleteWarningQuiz(string payload)
        {
            var warningQuizReponse = JsonConvert.DeserializeObject <TypeFormPayload>(payload);

            var accountDetail = await _commonCtx.CommonAccounts
                                .Include(m => m.Partition)
                                .Where(account => account.Id == warningQuizReponse.AccountId)
                                .SingleOrDefaultAsync();

            var _accountCtx = ContextsUtility.CreateAccountContext(Cryptography.Decrypt(accountDetail.Partition.ConnectionString));


            var citation = await _accountCtx.Citations.ForAccount(accountDetail.Id)
                           .Where(m => m.Id == warningQuizReponse.CitatoinId)
                           .OrderByDescending(m => m.CreateUtc)
                           .FirstOrDefaultAsync();

            //Close Citation
            citation.Status       = Data.Enums.CitationStatus.Closed;
            citation.ClosedReason = "Warning Quiz Complete";

            //Add warning quiz record
            var warningQuiz = new WarningQuizResponse {
                AccountId = accountDetail.Id, CitationId = citation.Id, Payload = payload, CreateUserId = citation.CreateUserId, UpdateUserId = citation.CreateUserId
            };

            _accountCtx.WarningEventRespones.Add(warningQuiz);
            await _accountCtx.SaveChangesAsync();

            //Create Audit event
            _citationSvc.CreateAuditEvent(accountDetail.Id, citation.Id, "Quiz Completed", citation.CreateUserId, Data.Enums.CitationAuditEvent.QuizComplete);
        }
示例#2
0
        /// <summary>
        /// Creates a new new violation category in the account context for every partition.
        /// </summary>
        public async Task UpdateAccountViolation(CommonViolation commonViolation)
        {
            var allAccounts = await _commonCtx.CommonAccounts.AsNoTracking().Include(m => m.Partition).Where(m => m.Archived == false).ToListAsync();

            //Go through each account and add this CommonViolation to Violation
            foreach (var account in allAccounts)
            {
                using (var accountContext = ContextsUtility.CreateAccountContext(Cryptography.Decrypt(account.Partition.ConnectionString)))
                {
                    var accountViolation = await accountContext.Violations.Where(m => m.AccountId == account.Id && m.CommonViolationId == commonViolation.Id).SingleOrDefaultAsync();

                    if (accountViolation != null)
                    {
                        var accountViolationCategory = await accountContext.ViolationCategorys.AsNoTracking().Where(m => m.AccountId == account.Id && m.CommonCategoryId == commonViolation.CategoryId).SingleOrDefaultAsync();

                        if (accountViolationCategory != null)
                        {
                            accountViolation.CategoryId      = accountViolationCategory.Id;
                            accountViolation.Name            = commonViolation.Name;
                            accountViolation.Description     = commonViolation.Description;
                            accountViolation.HelpUrl         = commonViolation.HelpUrl;
                            accountViolation.Actions         = commonViolation.Actions;
                            accountViolation.RequiredFields  = commonViolation.RequiredFields;
                            accountViolation.ReminderMinutes = commonViolation.ReminderMinutes;
                            //accountViolation.WarningQuizUrl = commonViolation.WarningQuizUrl;

                            await accountContext.SaveChangesAsync();
                        }
                    }
                }
            }
        }
示例#3
0
        public async Task <ServiceResponse <GeoLocation> > ReverseGeoCodeCitation(Guid accountId, Guid citationId)
        {
            ServiceResponse <GeoLocation> result = null;

            //_logger.Error("Get Account");
            var commonAccount = _commonCtx.CommonAccounts.Include(m => m.Partition).AsNoTracking().Where(m => m.Id == accountId).SingleOrDefault();

            if (commonAccount != null)
            {
                var accountContext = ContextsUtility.CreateAccountContext(Cryptography.Decrypt(commonAccount.Partition.ConnectionString));

                var citation = accountContext.Citations.Where(m => m.Id == citationId).SingleOrDefault();
                if (citation != null)
                {
                    // _logger.Error("Call Service");

                    var geoCodeResults = _geoCodeService.ReverseCode(citation.Latitude, citation.Longitude).Result;

                    if (geoCodeResults != null && geoCodeResults.address != null)
                    {
                        citation.State      = geoCodeResults.address.state;
                        citation.Street     = geoCodeResults.address.road;
                        citation.City       = geoCodeResults.address.city;
                        citation.PostalCode = geoCodeResults.address.postcode;
                    }
                }

                accountContext.SaveChanges();
            }

            return(result);
        }
        /// <summary>
        /// Refunds the payment.  Adds a negative payment record to the Payments table against this citation
        /// </summary>
        /// <param name="paymentId"></param>
        /// <param name="accountNumber"></param>
        /// <param name="amountRefunded"></param>
        /// <returns></returns>
        public async Task RefundPayment(string paymentId, long accountNumber, int amountRefunded)
        {
            //Get Account Record
            var commonAccount = _commonCtx.CommonAccounts.Include(m => m.Partition).AsNoTracking().Where(m => m.Number == accountNumber).SingleOrDefault();

            if (commonAccount != null)
            {
                var accountContext = ContextsUtility.CreateAccountContext(Cryptography.Decrypt(commonAccount.Partition.ConnectionString));

                var payment = await accountContext.CitationPayments.Include(m => m.Citation).Where(m => m.ChargeId.Contains(paymentId)).FirstOrDefaultAsync();

                if (payment != null)
                {
                    payment.ChargeAmount = payment.ChargeAmount - amountRefunded;

                    var fineAmountRefunded = amountRefunded.PenniesToDollarAmount() - payment.ProcessingFee;

                    payment.Citation.Balance = payment.Citation.Balance - fineAmountRefunded;

                    await _citationSvc.CreateAuditEvent(commonAccount.Id, payment.CitationId, $"{string.Format("{0:C}",amountRefunded.PenniesToDollarAmount())} payment refunded", payment.CreateUserId, Data.Enums.CitationAuditEvent.CitationRefundPayment);
                }

                try
                {
                    accountContext.SaveChanges();
                }
                catch (Exception ex)

                {
                    _logger.Error(ex, $"Error trying to create Citation Refund Payment");
                }
            }
        }
示例#5
0
        /// <summary>
        /// Creates a new new violation category in the account context for every partition.
        /// </summary>
        public async Task UpdateAccountViolationCategory(CommonViolationCategory commonViolationCategory)
        {
            var allAccounts = await _commonCtx.CommonAccounts.AsNoTracking().Include(m => m.Partition).Where(m => m.Archived == false).ToListAsync();

            //Go through each account and add this CommonViolation to Violation
            foreach (var account in allAccounts)
            {
                using (var accountContext = ContextsUtility.CreateAccountContext(Cryptography.Decrypt(account.Partition.ConnectionString)))
                {
                    var accountViolationCategory = await accountContext.ViolationCategorys.Where(m => m.AccountId == account.Id && m.CommonCategoryId == commonViolationCategory.Id).SingleOrDefaultAsync();

                    if (accountViolationCategory != null)
                    {
                        var accountViolationType = await accountContext.ViolationTypes.AsNoTracking().Where(m => m.AccountId == account.Id && m.CommonViolationTypeId == commonViolationCategory.TypeId).SingleOrDefaultAsync();

                        if (accountViolationType != null)
                        {
                            accountViolationCategory.TypeId      = accountViolationType.Id;
                            accountViolationCategory.Name        = commonViolationCategory.Name;
                            accountViolationCategory.Description = commonViolationCategory.Description;

                            await accountContext.SaveChangesAsync();
                        }
                    }
                }
            }
        }
示例#6
0
        /// <summary>
        /// Creates a new new violation in the account context for every partition.
        /// </summary>
        public async Task CreateAccountViolation(CommonViolation commonViolation)
        {
            var allAccounts = await _commonCtx.CommonAccounts.AsNoTracking().Include(m => m.Partition).Where(m => m.Archived == false).ToListAsync();

            //Go through each account and add this CommonViolation to Violation
            foreach (var account in allAccounts)
            {
                using (var accountContext = ContextsUtility.CreateAccountContext(Cryptography.Decrypt(account.Partition.ConnectionString)))
                {
                    var accountViolationCategory = await accountContext.ViolationCategorys.AsNoTracking().Where(m => m.AccountId == account.Id && m.CommonCategoryId == commonViolation.CategoryId).SingleOrDefaultAsync();

                    if (accountViolationCategory != null)
                    {
                        var created          = DateTime.UtcNow;
                        var accountViolation = Mapper.Map <Violation>(commonViolation);

                        accountViolation.CategoryId           = accountViolationCategory.Id;
                        accountViolation.CustomRequiredFields = commonViolation.RequiredFields;
                        accountViolation.CustomActions        = commonViolation.Actions;
                        accountViolation.AccountId            = account.Id;
                        accountViolation.CreateUtc            = created; //Setting created and UpdatedUtc to the exact same value will let us know if this record has every been changed.
                        accountViolation.UpdateUtc            = created;

                        accountContext.Violations.Add(accountViolation);

                        await accountContext.SaveChangesAsync();
                    }
                }
            }
        }
示例#7
0
        /// <summary>
        /// If an event is created during the time of this citation
        /// AND this citation falls within the boundary of this event
        /// AND there is an ovveride price for this particluar violation.
        /// we ovveride the citation fee.
        /// </summary>
        /// <param name="accountId"></param>
        /// <param name="citationId"></param>
        /// <returns></returns>
        public async Task <ServiceResponse <bool> > OverrideCitationFee(Guid accountId, Guid citationId)
        {
            ServiceResponse <bool> result = null;

            //_logger.Error("Get Account");
            var commonAccount = _commonCtx.CommonAccounts.Include(m => m.Partition).AsNoTracking().Where(m => m.Id == accountId).SingleOrDefault();

            if (commonAccount != null)
            {
                var accountContext = ContextsUtility.CreateAccountContext(Cryptography.Decrypt(commonAccount.Partition.ConnectionString));

                var citation = accountContext.Citations.Include(m => m.Violation).Where(m => m.Id == citationId).SingleOrDefault();

                //Step 1) Check if there is an eventPrice for this violation
                var eventPrice = accountContext.EventViolationPrices.ForAccount(commonAccount.Id).Include(m => m.Event)
                                 .Where(m => m.ViolationId == citation.ViolationId).SingleOrDefault();


                if (eventPrice != null)
                {
                    //Step 2. Check if this citation falls within the dates of this citation
                    var specialEvents = accountContext.Events.Include(m => m.EventBoundaryCoordinates).ForAccount(commonAccount.Id)
                                        .Where(m => m.Start.HasValue && citation.CreateUtc >= m.Start)
                                        .Where(m => m.End.HasValue && citation.CreateUtc <= m.End).ToList();

                    foreach (var specialEvent in specialEvents)
                    {
                        var eventCoords = accountContext.EventBoundaryCoordinates.ForAccount(commonAccount.Id).Where(m => m.EventId == specialEvent.Id).OrderBy(m => m.Order).ToList();
                        //Step 2) See if this citation falls inside the coordinates of the event
                        Dictionary <decimal, decimal> coords = eventCoords.ToDictionary(m => m.Latitude, m => m.Longitude);
                        if (IsLatLongIsnPolygon(citation.Latitude, citation.Longitude, coords))
                        {
                            citation.FineAmount = eventPrice.Fee;
                            try
                            {
                                accountContext.SaveChanges();
                            }
                            catch (Exception ex)

                            {
                                _logger.Error(ex, $"Error trying to create Override Citation Fee for Account:{accountId} Citation:{citation}");
                            }
                        }
                    }
                }
            }

            return(result);
        }
示例#8
0
        public async Task <Citation> GetCitation(long accountNumber, int citationNumber)
        {
            var accountDetail = await _commonCtx.CommonAccounts
                                .Include(m => m.Partition)
                                .Where(account => account.Number == accountNumber)
                                .SingleOrDefaultAsync();

            var _accountCtx = ContextsUtility.CreateAccountContext(Cryptography.Decrypt(accountDetail.Partition.ConnectionString));


            var citation = await _accountCtx.Citations.ForAccount(accountDetail.Id)
                           .Where(m => m.CitationNumber == citationNumber)
                           .OrderByDescending(m => m.CreateUtc)
                           .FirstOrDefaultAsync();

            return(citation);
        }
        /// <summary>
        /// Update User CommonAccount Profile
        /// </summary>
        /// <param name="commonAccount"></param>
        /// <param name="createdById"></param>
        /// <returns></returns>
        public async Task <ServiceResponse <CommonAccount> > UpdateSettingAccount(CommonAccount commonAccount, Guid createdById)
        {
            var result = new ServiceResponse <CommonAccount>();

            try
            {
                using (var scope = _commonCtx.Database.BeginTransaction())
                {
                    _commonCtx.CommonAccounts.Update(commonAccount);
                    await _commonCtx.SaveChangesAsync();


                    //update CommonAccountSettings table
                    var accountSettingDetail = await _commonCtx.CommonAccountSettings.SingleOrDefaultAsync(a => a.Id == commonAccount.Id);

                    accountSettingDetail.UpdateUserId = createdById;
                    accountSettingDetail.UpdateUtc    = DateTime.UtcNow;
                    _commonCtx.CommonAccountSettings.Update(accountSettingDetail);
                    await _commonCtx.SaveChangesAsync();

                    //update accounts table from selected partition
                    var accountCtx = ContextsUtility.CreateAccountContext(Cryptography.Decrypt(commonAccount.Partition.ConnectionString));

                    var AccountsDetail = await accountCtx.Accounts.SingleOrDefaultAsync(a => a.Id == commonAccount.Id);

                    AccountsDetail.Name         = commonAccount.Name;
                    AccountsDetail.UpdateUserId = createdById;
                    AccountsDetail.UpdateUtc    = DateTime.UtcNow;

                    accountCtx.Accounts.Update(AccountsDetail);
                    await accountCtx.SaveChangesAsync();

                    scope.Commit();
                }
            }
            catch (Exception ex)
            {
                _logger.Error(ex, "Error updating an Account");

                throw ex;
            }

            return(result);
        }
示例#10
0
        /// <summary>
        /// A violation can have a reminder attached to it.  That can be used when a violation requires a following piece of evidence.
        /// For example.  If you're reporting an abnandoned vehicle, you may be reminded after 24 hours to submit another video.
        /// </summary>
        /// <param name="accountId"></param>
        /// <param name="citationId"></param>
        /// <param name="userId"></param>
        /// <returns></returns>
        public async Task <ServiceResponse <bool> > CreateCitationReminder(Guid accountId, Guid citationId, Guid?userId)
        {
            ServiceResponse <bool> result = null;

            //_logger.Error("Get Account");
            var commonAccount = _commonCtx.CommonAccounts.Include(m => m.Partition).AsNoTracking().Where(m => m.Id == accountId).SingleOrDefault();

            if (commonAccount != null)
            {
                var accountContext = ContextsUtility.CreateAccountContext(Cryptography.Decrypt(commonAccount.Partition.ConnectionString));

                var citation = accountContext.Citations.Include(m => m.Violation).Where(m => m.Id == citationId).SingleOrDefault();
                if (citation != null && citation.Violation.ReminderMinutes.HasValue && citation.Violation.ReminderMinutes.Value > 0)
                {
                    var reminderDelivery = DateTime.UtcNow.AddMinutes(citation.Violation.ReminderMinutes.Value);


                    var newCitationReminder = new CitationReminder {
                        AccountId = accountId, CitationId = citationId, DeliveryDateUTC = reminderDelivery, Message = citation.Violation.ReminderMessage
                    };

                    if (userId.HasValue)
                    {
                        newCitationReminder.CreateUserId = userId.Value;
                        newCitationReminder.UpdateUserId = userId.Value;
                    }

                    accountContext.CitationReminders.Add(newCitationReminder);
                }

                try
                {
                    accountContext.SaveChanges();
                }
                catch (Exception ex)

                {
                    _logger.Error(ex, $"Error trying to create CitationReminder for Account:{accountId} Citation:{citation} for user:{userId}");
                }
            }

            return(result);
        }
        /// <summary>
        /// Create or Update a user information across all partiations
        /// </summary>
        /// <param name="commonUser"></param>
        /// <param name="createdById"></param>
        /// <returns></returns>
        public async Task SaveAccountUser(CommonUser commonUser, Guid createdById, bool isAdmin = false)
        {
            //Get all accounts that this user belongs to
            var accounts = await _commonCtx.UserAccounts.Include(m => m.Account).ThenInclude(m => m.Partition).Where(m => m.UserId == commonUser.Id).ToListAsync();

            //Go through each account and create or update the user's informatoin
            foreach (var account in accounts)
            {
                //generate an account context for this account
                var accountCtx = ContextsUtility.CreateAccountContext(Cryptography.Decrypt(account.Account.Partition.ConnectionString));

                //check to see if this user exists in the account
                var user = await accountCtx.AccountUsers.SingleOrDefaultAsync(m => m.Id == commonUser.Id);

                //If the user doesn't exit, create them.
                if (user == null)
                {
                    user = new AccountUser
                    {
                        Id              = commonUser.Id, //IMPORTANT: CommonUser.Id and AccountUser.Id must always match
                        FirstName       = commonUser.FirstName,
                        MiddleName      = commonUser.MiddleName,
                        LastName        = commonUser.LastName,
                        Email           = commonUser.Email,
                        ProfileImageKey = commonUser.ProfileImageKey,
                        CreateUserId    = createdById,
                        UpdateUserId    = createdById
                    };

                    accountCtx.AccountUsers.Add(user);
                }
                else
                {
                    user.FirstName       = commonUser.FirstName;
                    user.MiddleName      = commonUser.MiddleName;
                    user.LastName        = commonUser.LastName;
                    user.UpdateUserId    = createdById;
                    user.UpdateUtc       = DateTime.UtcNow;
                    user.ProfileImageKey = commonUser.ProfileImageKey;
                }
                await accountCtx.SaveChangesAsync();
            }
        }
        /// <summary>
        /// Look for <see cref="Data.Models.Common.CommonAccount" /> in cache. If found, return it. If not found,
        /// load it from the database and cache it.
        /// </summary>
        /// <param name="accountNumber"></param>
        /// <returns></returns>
        public async Task <CachedAccount> GetCachedAccountAsync(long accountNumber)
        {
            var cacheKey = WebCacheKey.CommonAccount(accountNumber);

            // Try to pull it from the cache first.
            var cachedAccount = await _cache.GetWithSlidingExpirationAsync <CachedAccount>(cacheKey, _commonAccountCacheExpiry);

            if (cachedAccount != null)
            {
                return(cachedAccount);
            }

            // Not in cache. Check the database.
            var commonAccount = await _commonCtx.CommonAccounts.AsNoTracking()
                                .Include(ca => ca.Partition)
                                .Include(ca => ca.Settings)
                                .Include(ca => ca.City)
                                .Include(ca => ca.CommonAccountViolationTypes)
                                .SingleOrDefaultAsync(ca => ca.Number == accountNumber);

            if (commonAccount == null)
            {
                // Account not found.
                return(null);
            }

            cachedAccount = Mapper.Map <CachedAccount>(commonAccount);

            var commonViolationTypes = await _commonCtx.CommonAccountViolationTypes.Where(m => m.AccountId == commonAccount.Id).Select(m => m.ViolationTypeId).ToListAsync();

            var accountCtx     = ContextsUtility.CreateAccountContext(Cryptography.Decrypt(commonAccount.Partition.ConnectionString));
            var violationTypes = await accountCtx.ViolationTypes.ForAccount(commonAccount.Id).Where(m => commonViolationTypes.Contains(m.CommonViolationTypeId)).ToListAsync();


            cachedAccount.ViolationTypes = Mapper.Map <ViolationTypeModel[]>(violationTypes);


            // Found it. Add it to the cache.
            await _cache.SetAsync(cacheKey, cachedAccount, _commonAccountCacheExpiry);

            return(cachedAccount);
        }
示例#13
0
        /// <summary>
        /// Creates a new new violation type in the account context for every partition.
        /// </summary>
        public async Task CreateAccountViolationType(CommonViolationType commonViolationType)
        {
            var allAccounts = await _commonCtx.CommonAccounts.AsNoTracking().Include(m => m.Partition).Where(m => m.Archived == false).ToListAsync();

            //Go through each account and add this CommonViolation to Violation
            foreach (var account in allAccounts)
            {
                using (var accountContext = ContextsUtility.CreateAccountContext(Cryptography.Decrypt(account.Partition.ConnectionString)))
                {
                    var created       = DateTime.UtcNow;
                    var violationType = Mapper.Map <ViolationType>(commonViolationType);

                    violationType.AccountId = account.Id;
                    violationType.CreateUtc = created; //Setting created and UpdatedUtc to the exact same value will let us know if this record has every been changed.
                    violationType.UpdateUtc = created;

                    accountContext.ViolationTypes.Add(violationType);

                    await accountContext.SaveChangesAsync();
                }
            }
        }
示例#14
0
        /// <summary>
        /// populate all violations in the account context for selected partition.
        /// </summary>
        public async Task PopulateViolationsForAccount(CommonAccount commonAccount, Guid createdById)
        {
            var AllViolationType = await _commonCtx.CommonViolationTypes.AsNoTracking().Where(m => m.Disabled == false).ToListAsync();

            var AllViolationCategory = await _commonCtx.CommonViolationCategories.AsNoTracking().Where(m => m.Disabled == false).ToListAsync();

            var AllViolation = await _commonCtx.CommonViolations.AsNoTracking().Where(m => m.Disabled == false).ToListAsync();

            //Go through each account and add this CommonViolation to Violation
            foreach (var violationType in AllViolationType)
            {
                using (var accountContext = ContextsUtility.CreateAccountContext(Cryptography.Decrypt(commonAccount.Partition.ConnectionString)))
                {
                    var created        = DateTime.UtcNow;
                    var violationTypes = Mapper.Map <ViolationType>(violationType);

                    violationTypes.AccountId             = commonAccount.Id;
                    violationTypes.CreateUtc             = created; //Setting created and UpdatedUtc to the exact same value will let us know if this record has every been changed.
                    violationTypes.UpdateUtc             = created;
                    violationTypes.CommonViolationTypeId = violationType.Id;

                    accountContext.ViolationTypes.Add(violationTypes);

                    await accountContext.SaveChangesAsync();
                    await PurgeAccountViolation(commonAccount.Id);
                }
            }

            // add entries in violation category in the account context for this account
            foreach (var ViolationCategory in AllViolationCategory)
            {
                using (var accountContext = ContextsUtility.CreateAccountContext(Cryptography.Decrypt(commonAccount.Partition.ConnectionString)))
                {
                    var created = DateTime.UtcNow;
                    var accountViolationType = await accountContext.ViolationTypes.AsNoTracking().Where(m => m.AccountId == commonAccount.Id && m.CommonViolationTypeId == ViolationCategory.TypeId).SingleOrDefaultAsync();

                    if (accountViolationType != null)
                    {
                        var violationCategory = Mapper.Map <ViolationCategory>(ViolationCategory);

                        violationCategory.TypeId           = accountViolationType.Id;
                        violationCategory.AccountId        = commonAccount.Id;
                        violationCategory.CreateUtc        = created; //Setting created and UpdatedUtc to the exact same value will let us know if this record has every been changed.
                        violationCategory.UpdateUtc        = created;
                        violationCategory.CommonCategoryId = ViolationCategory.Id;

                        accountContext.ViolationCategorys.Add(violationCategory);

                        await accountContext.SaveChangesAsync();
                        await PurgeAccountViolation(commonAccount.Id);
                    }
                }
            }

            // add entries in violations in the account context for this account
            foreach (var Violation in AllViolation)
            {
                using (var accountContext = ContextsUtility.CreateAccountContext(Cryptography.Decrypt(commonAccount.Partition.ConnectionString)))
                {
                    var created = DateTime.UtcNow;
                    var accountViolationCategory = await accountContext.ViolationCategorys.AsNoTracking().Where(m => m.AccountId == commonAccount.Id && m.CommonCategoryId == Violation.CategoryId).SingleOrDefaultAsync();

                    if (accountViolationCategory != null)
                    {
                        var violation = Mapper.Map <Violation>(Violation);

                        violation.CategoryId           = accountViolationCategory.Id;
                        violation.AccountId            = commonAccount.Id;
                        violation.CreateUtc            = created; //Setting created and UpdatedUtc to the exact same value will let us know if this record has every been changed.
                        violation.UpdateUtc            = created;
                        violation.CommonViolationId    = Violation.Id;
                        violation.CustomActions        = Violation.Actions;
                        violation.CustomRequiredFields = Violation.RequiredFields;

                        accountContext.Violations.Add(violation);

                        await accountContext.SaveChangesAsync();
                        await PurgeAccountViolation(commonAccount.Id);
                    }
                }
            }
        }
        /// <summary>
        /// Update an existing Account in the Common and Account partitions.
        /// Also update a user in the Account Partition.
        /// </summary>
        /// <param name="commonAccount"></param>
        /// <param name="createdById"></param>
        /// <returns></returns>
        public async Task <ServiceResponse <CommonAccount> > UpdateAccount(CommonAccount commonAccount, Guid createdById, int AccountNumber, List <AccountViolationType> AccViolationType)
        {
            var result = new ServiceResponse <CommonAccount>();

            try
            {
                using (var scope = _commonCtx.Database.BeginTransaction())
                {
                    //update common account table
                    var accountDetail = await _commonCtx.CommonAccounts.Include(m => m.Partition).Include(m => m.Settings).SingleOrDefaultAsync(a => a.Id == commonAccount.Id);


                    var accountCtx = ContextsUtility.CreateAccountContext(Cryptography.Decrypt(accountDetail.Partition.ConnectionString));


                    accountDetail.UpdateUserId      = createdById;
                    accountDetail.UpdateUtc         = DateTime.Now;
                    accountDetail.Name              = commonAccount.Name;
                    accountDetail.OwnerUserId       = commonAccount.OwnerUserId;
                    accountDetail.StorageBucketName = commonAccount.StorageBucketName;
                    accountDetail.CitationWorkflow  = commonAccount.CitationWorkflow;
                    accountDetail.Features          = commonAccount.Features;

                    _commonCtx.CommonAccounts.Update(accountDetail);
                    await _commonCtx.SaveChangesAsync();


                    //update accounts table from selected partition
                    var AccountsDetail = await accountCtx.Accounts.SingleOrDefaultAsync(a => a.Id == commonAccount.Id);

                    AccountsDetail.Name         = commonAccount.Name;
                    AccountsDetail.UpdateUserId = createdById;
                    AccountsDetail.UpdateUtc    = DateTime.UtcNow;

                    accountCtx.Accounts.Update(AccountsDetail);
                    await accountCtx.SaveChangesAsync();

                    //update user accounts table
                    if (commonAccount.OwnerUserId != null)
                    {
                        //Check to see if the owner exists in the User Account Table.
                        var userAccount = await _commonCtx.UserAccounts.SingleOrDefaultAsync(a => a.AccountId == commonAccount.Id && a.UserId == commonAccount.OwnerUserId);

                        if (userAccount == null)
                        {
                            CommonUserAccount NewuserAccount = new CommonUserAccount();
                            NewuserAccount.CreateUserId = createdById;
                            NewuserAccount.AccountId    = commonAccount.Id;
                            NewuserAccount.UpdateUserId = createdById;
                            NewuserAccount.UserId       = commonAccount.OwnerUserId;
                            NewuserAccount.Permissions  = (AccountPermissions)Enum.GetValues(typeof(AccountPermissions)).Cast <int>().Sum();

                            _commonCtx.UserAccounts.Add(NewuserAccount);

                            await _commonCtx.SaveChangesAsync();

                            var commonUser = await _commonCtx.Users.SingleAsync(m => m.Id == commonAccount.OwnerUserId);

                            //Add any new users to acconts
                            await SaveAccountUser(commonUser, createdById);
                        }
                    }


                    //Remove the current violation types
                    var AccountViolationType = await _commonCtx.CommonAccountViolationTypes.Where(av => av.AccountId == commonAccount.Id).ToListAsync();

                    _commonCtx.CommonAccountViolationTypes.RemoveRange(AccountViolationType);
                    await _commonCtx.SaveChangesAsync();


                    //Add new violatoin types from the page
                    foreach (var Types in AccViolationType)
                    {
                        if (Types.IsCheckedViolation == true)
                        {
                            CommonAccountViolationType AcntViolationType = new CommonAccountViolationType();
                            AcntViolationType.CreateUserId    = createdById;
                            AcntViolationType.AccountId       = commonAccount.Id;
                            AcntViolationType.UpdateUserId    = createdById;
                            AcntViolationType.ViolationTypeId = Types.TypeId;

                            _commonCtx.CommonAccountViolationTypes.Add(AcntViolationType);
                            await _commonCtx.SaveChangesAsync();
                        }
                    }
                    scope.Commit();

                    //Purge common accounts cache
                    var cacheKey = WebCacheKey.CommonAccount(accountDetail.Number);
                    await _cache.RemoveAsync(cacheKey);
                }
            }
            catch (Exception ex)
            {
                _logger.Error(ex, "Error updating an Account");

                throw ex;
            }

            return(result);
        }
        /// <summary>
        /// Creates a new Account in the Common and Account partitions.
        /// Also creates a user in the Account Partition if one doesn't exist.
        /// </summary>
        /// <param name="commonAccount"></param>
        /// <param name="user"></param>
        /// <param name="createdById"></param>
        /// <returns></returns>
        public async Task <ServiceResponse <CommonAccount> > CreateAccount(CommonAccount commonAccount, Guid createdById, List <AccountViolationType> AccViolationType, long CitationCounter)
        {
            var result = new ServiceResponse <CommonAccount>();

            try
            {
                using (var scope = _commonCtx.Database.BeginTransaction())
                {
                    //Get the correct account database based on the partition that was chosen for the account.
                    var accountCtx = ContextsUtility.CreateAccountContext(Cryptography.Decrypt(commonAccount.Partition.ConnectionString));

                    if (accountCtx == null)
                    {
                        _logger.Error($"Account context does not exists for partition: {Cryptography.Decrypt(commonAccount.Partition.ConnectionString)}");

                        throw new Exception("Account context does not exists");
                    }

                    //Generate a random account number
                    commonAccount.Number = await GetNextAccountNumberAsync();

                    commonAccount.CreateUserId = createdById;
                    commonAccount.UpdateUserId = createdById;

                    //Create empty account settings
                    commonAccount.Settings = new CommonAccountSettings {
                    };
                    commonAccount.Settings.CreateUserId = createdById;
                    commonAccount.Settings.UpdateUserId = createdById;

                    _commonCtx.CommonAccounts.Add(commonAccount);

                    await _commonCtx.SaveChangesAsync();


                    //Update the count on the partition to let us know how many account reside on one database.
                    commonAccount.Partition.Occupancy = commonAccount.Partition.Occupancy + 1;
                    _commonCtx.Partitions.Update(commonAccount.Partition);


                    //If a Owner is selected, create a user account assosication.
                    if (commonAccount.OwnerUserId != null)
                    {
                        CommonUserAccount userAccount = new CommonUserAccount();
                        userAccount.CreateUserId = createdById;
                        userAccount.AccountId    = commonAccount.Id;
                        userAccount.UpdateUserId = createdById;
                        userAccount.UserId       = commonAccount.OwnerUserId;
                        userAccount.Permissions  = (AccountPermissions)Enum.GetValues(typeof(AccountPermissions)).Cast <int>().Sum();

                        _commonCtx.UserAccounts.Add(userAccount);
                        await _commonCtx.SaveChangesAsync();

                        var commonUser = await _commonCtx.Users.SingleAsync(m => m.Id == commonAccount.OwnerUserId);

                        //Add any new users to acconts
                        await SaveAccountUser(commonUser, createdById);
                    }

                    //Add Account in account context
                    //The Ids for the Account in AccountContext and CommonAccount in CommonContext are going to be exactly the same.
                    accountCtx.Accounts.Add(new Account {
                        Id = commonAccount.Id, Name = commonAccount.Name, CreateUserId = createdById, UpdateUserId = createdById
                    });

                    await accountCtx.SaveChangesAsync();


                    foreach (var Type in AccViolationType)
                    {
                        if (Type.IsCheckedViolation == true)
                        {
                            CommonAccountViolationType AccountViolationType = new CommonAccountViolationType();
                            AccountViolationType.CreateUserId    = createdById;
                            AccountViolationType.AccountId       = commonAccount.Id;
                            AccountViolationType.UpdateUserId    = createdById;
                            AccountViolationType.ViolationTypeId = Type.TypeId;

                            _commonCtx.CommonAccountViolationTypes.Add(AccountViolationType);
                        }
                    }

                    await _commonCtx.SaveChangesAsync();

                    await _violationSvc.PopulateViolationsForAccount(commonAccount, createdById);

                    Counter count = new Counter()
                    {
                        AccountId    = commonAccount.Id,
                        Name         = "Citations",
                        NextValue    = CitationCounter,
                        CreateUserId = commonAccount.OwnerUserId.Value,
                        UpdateUserId = commonAccount.OwnerUserId.Value
                    };
                    accountCtx.Counters.Add(count);

                    await accountCtx.SaveChangesAsync();

                    scope.Commit();
                }
            }
            catch (Exception ex)
            {
                _logger.Error(ex, "Error creating new Account");


                throw ex;
            }

            return(result);
        }