public async Task <IActionResult> AssociateUser([FromBody] AccountUserAssociationModel model)
        {
            var response = new APIResponse <CommonUserAccountModel>()
            {
                Success = true
            };

            var commonUser = await CommonContext.Users.SingleOrDefaultAsync(m => m.Id == model.UserId);

            if (commonUser == null)
            {
                response.Success = false;
                response.Message = "User could not be found";
            }
            else
            {
                var commonUserAccount = await CommonContext.UserAccounts.Where(m => m.UserId == model.UserId && m.AccountId == model.AccountId).SingleOrDefaultAsync();

                //If these is no association, create it.
                if (commonUserAccount == null)
                {
                    commonUserAccount = new CommonUserAccount {
                        AccountId = model.AccountId, UserId = model.UserId, CreateUserId = model.UserId, UpdateUserId = model.UserId
                    };

                    CommonContext.UserAccounts.Add(commonUserAccount);
                    await CommonContext.SaveChangesAsync();
                }

                await _commonAccountSvc.SaveAccountUser(commonUser, commonUser.CreateUserId);

                response.Data = Mapper.Map <CommonUserAccountModel>(commonUserAccount);
            }

            return(Ok(response));
        }
        public async Task <ActionResult> CreatePassword(CreatePassword model)
        {
            if (ModelState.IsValid)
            {
                //Create new User and Account
                var user = new CommonUser();
                user.Email      = model.InvitedEmail;
                user.FirstName  = model.FirstName;
                user.LastName   = model.LastName;
                user.Permission = model.SystemPermission;
                user.SetPassword(model.Password);


                //Check Account
                var commonAccount = await CommonContext.CommonAccounts.Where(m => m.Id == model.AccountId).SingleOrDefaultAsync();

                var vendorDetail = await _accountCtx.Vendors.Where(x => x.Id == model.VendorId).SingleOrDefaultAsync();


                if (commonAccount == null)
                {
                    ViewBag.SucessMessage = "Account not found";
                    return(View(model));
                }

                CommonUserAccount userAccount = new CommonUserAccount();
                userAccount.CreateUserId = commonAccount.OwnerUserId.Value;
                userAccount.AccountId    = commonAccount.Id;
                userAccount.UpdateUserId = commonAccount.OwnerUserId.Value;
                userAccount.UserId       = user.Id;
                userAccount.Permissions  = (AccountPermissions)model.Permission;

                if (vendorDetail != null)
                {
                    user.Permission = SystemPermissions.Vendor;
                }

                using (var tx = CommonContext.Database.BeginTransaction())
                {
                    CommonContext.Users.Add(user);
                    await CommonContext.SaveChangesAsync();

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

                    tx.Commit();
                }

                //Create AccountUser
                var accountUser = new AccountUser
                {
                    Id        = userAccount.UserId.Value,
                    FirstName = user.FirstName,
                    LastName  = user.LastName,
                    Email     = user.Email
                };

                _accountCtx.AccountUsers.Add(accountUser);

                if (vendorDetail != null)
                {
                    AccountUserVendor accountUserVendor = new AccountUserVendor();
                    accountUserVendor.VendorId      = vendorDetail.Id;
                    accountUserVendor.AccountUserId = accountUser.Id;

                    _accountCtx.AccountUserVendors.Add(accountUserVendor);
                }

                await _accountCtx.SaveChangesAsync();

                await SignInUser(user, false);

                return(RedirectToAction("Index", "Accounts"));
            }
            return(View(model));
        }
        /// <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);
        }
        public async Task <ActionResult> AcceptInvite(AcceptInvite model)
        {
            //Check to see if this user exists in Users
            var existingUser = await CommonContext.Users.Where(m => m.Email == model.InvitedEmail).AnyAsync();

            if (existingUser)
            {
                //Check to see if this user already belongs to the account
                //Users can belong to multiple accounts, we need to filter by accountID and InvitedEmail
                var existingAccountUser = await CommonContext.UserAccounts.Include(x => x.User).Where(m => m.User.Email == model.InvitedEmail && m.AccountId == model.AccountId).AnyAsync();

                if (!existingAccountUser)
                {
                    //Get exists User Detail
                    var user = CommonContext.Users.Where(m => m.Email == model.InvitedEmail).SingleOrDefault();

                    //Get Account detail using accountId
                    var commonAccount = await CommonContext.CommonAccounts.Where(m => m.Id == model.AccountId).SingleOrDefaultAsync();

                    var vendorDetail = await _accountCtx.Vendors.Where(x => x.Id == model.VendorId).SingleOrDefaultAsync();

                    if (commonAccount == null)
                    {
                        ViewBag.SucessMessage = "Account not found";
                        return(View(model));
                    }

                    CommonUserAccount userAccount = new CommonUserAccount();
                    userAccount.CreateUserId = commonAccount.OwnerUserId.Value;
                    userAccount.AccountId    = commonAccount.Id;
                    userAccount.UpdateUserId = commonAccount.OwnerUserId.Value;
                    userAccount.UserId       = user.Id;
                    userAccount.Permissions  = (AccountPermissions)model.Permission;

                    using (var tx = CommonContext.Database.BeginTransaction())
                    {
                        CommonContext.UserAccounts.Add(userAccount);
                        await CommonContext.SaveChangesAsync();

                        tx.Commit();
                    }

                    var accountUser = await _accountCtx.AccountUsers.Where(m => m.Id == user.Id).SingleOrDefaultAsync();

                    if (accountUser == null)
                    {
                        //Create AccountUser
                        accountUser = new AccountUser()
                        {
                            Id        = user.Id,
                            FirstName = user.FirstName,
                            LastName  = user.LastName,
                            Email     = user.Email,
                        };
                        _accountCtx.AccountUsers.Add(accountUser);
                        await _accountCtx.SaveChangesAsync();
                    }

                    if (vendorDetail != null)
                    {
                        AccountUserVendor accountUserVendor = new AccountUserVendor();
                        accountUserVendor.VendorId      = vendorDetail.Id;
                        accountUserVendor.AccountUserId = accountUser.Id;

                        user.Permission = SystemPermissions.Vendor;
                        CommonContext.SaveChanges();

                        using (var tx = _accountCtx.Database.BeginTransaction())
                        {
                            _accountCtx.AccountUserVendors.Add(accountUserVendor);
                            await _accountCtx.SaveChangesAsync();

                            tx.Commit();
                        }
                    }

                    return(RedirectToAction("Index", "Accounts"));
                }
                else
                {
                    ViewBag.SucessMessage = " Already Account user.";
                    return(View(model));
                }
            }
            else
            {
                CreatePassword pwdmodel = new Models.User.CreatePassword();
                pwdmodel.AccountId    = model.AccountId;
                pwdmodel.AccountName  = model.AccountName;
                pwdmodel.InvitedEmail = model.InvitedEmail;
                string[] name = model.Name.Split(' ');
                pwdmodel.FirstName        = name[0];
                pwdmodel.LastName         = name[1];
                pwdmodel.Permission       = model.Permission;
                pwdmodel.VendorId         = model.VendorId;
                pwdmodel.SystemPermission = model.SystemPermission;
                return(View("CreatePassword", pwdmodel));
            }
        }
        /// <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);
        }