// ReSharper disable once InconsistentNaming
        public async void Can_GET_All_Account_Types()
        {
            // Arrange
            _ctrl = new AccountTypeController(_repository, _repositoryAsset, _identityService) {
                Request = new HttpRequestMessage { RequestUri = new Uri(UrlBase + "/AccountType") },
                Configuration = new HttpConfiguration()
            };
               

            // Act
            var acctTypes = await _ctrl.GetAllAccounts();
            
            // Assert
            Assert.IsNotNull(acctTypes);
          
        }
Пример #2
0
 private Position MapVmToPosition(PositionVm sourceData)
 {
     var acctTypeCtrl = new AccountTypeController(_repositoryAccountType, _repositoryAsset, _identityService, _repositoryInvestor);
     return new Position
            {
                // ReSharper disable once PossibleInvalidOperationException
                PurchaseDate = (DateTime) sourceData.DateOfPurchase,
                Quantity = sourceData.Qty,
                MarketPrice = sourceData.UnitCosts,
                InvestorKey = Utilities.GetInvestorId(_repositoryInvestor, _identityService.CurrentUser).ToString(),
                AcctTypeId = sourceData.ReferencedAccount.KeyId,
                PositionAssetId = sourceData.ReferencedAssetId, 
                LastUpdate = DateTime.Now,
                TickerSymbol = sourceData.ReferencedTickerSymbol,
                Account = acctTypeCtrl.MapVmToAccountType(sourceData.ReferencedAccount),
                Url = sourceData.Url
            };
 }
Пример #3
0
        // ReSharper disable once InconsistentNaming
        public async Task Controller_can_GET_all_entered_account_types_for_an_investor() 
        {
            // Arrange  
            _ctrl = new AccountTypeController(_mockRepoAcctType.Object, _mockRepoAsset.Object, _mockIdentitySvc.Object) {
                Request = new HttpRequestMessage { RequestUri = new Uri("http://localhost/Pims.Web.Api/api/AccountType/none") },
                Configuration = new HttpConfiguration()
            };

            // Act 
            var accountTypes = await _ctrl.GetAllAccountsForInvestor("none") as OkNegotiatedContentResult<IQueryable<string>>;


            // Assert
            Assert.IsNotNull(accountTypes);
            Assert.That(accountTypes.Content.Contains("Roth-IRA"));
            Assert.That(accountTypes.Content.All(s => s != string.Empty));
            Assert.That(accountTypes.Content.Count(), Is.GreaterThanOrEqualTo(3));
        }
Пример #4
0
        public async Task<IHttpActionResult> CreateNewAsset([FromBody] AssetCreationVm submittedAsset)
        {
            _currentInvestor = _identityService.CurrentUser; 
            _repositoryInvestor.UrlAddress = ControllerContext.Request.RequestUri.ToString();

            // Confirm investors' registration for idempotent operations.
            var registeredInvestor = await Task.FromResult(_repositoryInvestor.Retreive(u => u.EMailAddr.Trim() == _currentInvestor.Trim()));
            if (!registeredInvestor.Any())
                return BadRequest("Unable to create new Asset, no registration found for investor : " + _currentInvestor);

            if (!ModelState.IsValid) {
                return ResponseMessage(new HttpResponseMessage {
                                            StatusCode = HttpStatusCode.BadRequest,
                                            ReasonPhrase = "Invalid/Incomplete required 'ModelState' data received for new Asset creation."
                });
            }

            // Reconfirm required Position data exist.
            if (!submittedAsset.PositionsCreated.Any())
                return BadRequest("Unable to create new Asset, no Position data found.");

            // ACCOUNT TYPE.
            var acctTypeCtrl = new AccountTypeController(_repositoryAccountType, _repository, _identityService, _repositoryInvestor);
            var existingAcctTypes = await acctTypeCtrl.GetAllAccounts() as OkNegotiatedContentResult<IList<AccountTypeVm>>;
            if(existingAcctTypes == null)
                return BadRequest("Unable to retreive required AccountType data for Asset creation.");


            var duplicateCheck = GetByTicker(submittedAsset.AssetTicker.Trim());
            if(duplicateCheck.Result.ToString().Contains("OkNegotiatedContent"))
                return ResponseMessage(new HttpResponseMessage {
                                                        StatusCode = HttpStatusCode.Conflict,
                                                        ReasonPhrase = "No Asset created; duplicate Asset found for " + submittedAsset.AssetTicker.Trim()
                });

            submittedAsset.AssetInvestorId = registeredInvestor.First().InvestorId.ToString();                      // Required entry.
            submittedAsset.AssetClassificationId = await Task.FromResult(_repositoryAssetClass.Retreive(ac => ac.Description.Trim() == submittedAsset.AssetClassification.Trim())
                                                                                              .AsQueryable()
                                                                                              .First()
                                                                                              .KeyId.ToString());   // Required entry.


            // PROFILE.
            // Submited Asset must contain the following minimum Profile information, per client validation checks.
            var profileLastUpdate = Convert.ToDateTime(submittedAsset.ProfileToCreate.LastUpdate) ;
            
            if(submittedAsset.ProfileToCreate.TickerSymbol.IsEmpty() || 
               submittedAsset.ProfileToCreate.TickerDescription.IsEmpty() ||
               submittedAsset.ProfileToCreate.Price == 0 || 
               profileLastUpdate == DateTime.MinValue ||  // unassigned
               submittedAsset.ProfileToCreate.Url.IsEmpty())
                    return BadRequest("Asset creation aborted: minimum Profile data [ticker,tickerDesc,Price,lastUpDate, or Url] is missing or invalid.");

            var existingProfile = await Task.FromResult(_repositoryProfile.Retreive(p => p.TickerSymbol.Trim() == submittedAsset.AssetTicker.Trim())
                                                                          .AsQueryable());

            var profileCtrl = new ProfileController(_repositoryProfile);
            if (existingProfile.Any())
            {
                if (existingProfile.First().LastUpdate >= DateTime.Now.AddHours(-24))
                    submittedAsset.ProfileToCreate.ProfileId = existingProfile.First().ProfileId;
                else
                {
                    var updatedResponse = await profileCtrl.UpdateProfile(submittedAsset.ProfileToCreate) as OkNegotiatedContentResult<string>;
                    // We'll cancel Asset creation here, as out-of-date Profile data would render inaccurate income projections, should the user
                    // choose to use these projections real-time.
                    if (updatedResponse == null || !updatedResponse.Content.Contains("successfully"))
                        return BadRequest("Asset creation aborted: unable to update Profile data.");
                }
            }
            else
            {
                var createdProfile = await profileCtrl.CreateNewProfile(submittedAsset.ProfileToCreate) as CreatedNegotiatedContentResult<Profile>;
                if (createdProfile == null)
                    return BadRequest("Error creating new Profile.");

                submittedAsset.ProfileToCreate.ProfileId = createdProfile.Content.ProfileId;
            }



            // ASSET.
            var newAsset = await SaveAssetAndGetId(submittedAsset) as CreatedNegotiatedContentResult<Asset>;;
            if (newAsset == null)
                return BadRequest("Error creating new Asset or AssetId.");

            submittedAsset.AssetIdentification = newAsset.Content.AssetId.ToString();


            
            // POSITION(S).
            var positionCtrl = new PositionController(_identityService, _repository, _repositoryInvestor, _repositoryPosition, _repositoryAccountType);
            for(var pos = 0; pos < submittedAsset.PositionsCreated.Count; pos++)
            {
                // ReSharper disable once AccessToModifiedClosure
                var positionAcctTypeId = existingAcctTypes.Content.Where(at => at.AccountTypeDesc.Trim().ToUpper() == submittedAsset.PositionsCreated.ElementAt(pos)
                                                                                                                          .PreEditPositionAccount
                                                                                                                          .ToUpper()
                                                                                                                          .Trim())
                                                                                                                          .AsQueryable()
                                                                                                                          .Select(at => at.KeyId);

                if (!positionAcctTypeId.Any())
                {
                    // Rollback Asset creation (via NH Cascade).
                    var deleteResponse = await DeleteAsset(submittedAsset.AssetTicker.Trim()) as OkNegotiatedContentResult<string>;
                    if(deleteResponse == null || deleteResponse.Content.Contains("Error"))
                        return BadRequest("Asset-Position creation aborted due to Asset rollback error for bad AccountType: " 
                                                                    + submittedAsset.PositionsCreated.ElementAt(pos).PreEditPositionAccount.Trim().ToUpper()); 

                    return BadRequest("Asset-Position creation aborted due to error retreiving AccountType for: " 
                                                                    + submittedAsset.PositionsCreated.ElementAt(pos).PreEditPositionAccount.Trim().ToUpper()); 
                }
                    

                submittedAsset.PositionsCreated.ElementAt(pos).ReferencedAccount.KeyId = positionAcctTypeId.First();                // Required entry.
                submittedAsset.PositionsCreated.ElementAt(pos).ReferencedAssetId = new Guid(submittedAsset.AssetIdentification);    // Required entry.
                submittedAsset.PositionsCreated.ElementAt(pos).Url = Utilities.GetBaseUrl(_repositoryInvestor.UrlAddress)
                                                                     + "Asset/"
                                                                     + submittedAsset.AssetTicker.Trim()
                                                                     + "/Position/"
                                                                     + submittedAsset.PositionsCreated.ElementAt(pos).PreEditPositionAccount.Trim();

                var createdPosition = await positionCtrl.CreateNewPosition(submittedAsset.PositionsCreated.ElementAt(pos)) as CreatedNegotiatedContentResult<Position>;
                if (createdPosition == null)
                {
                    // Rollback Asset creation.
                    var deleteResponse = await DeleteAsset(submittedAsset.AssetTicker.Trim()) as OkNegotiatedContentResult<string>;
                    if (deleteResponse == null || deleteResponse.Content.Contains("Error"))
                        return BadRequest("Asset-Position creation aborted due to Asset rollback error for Position: " 
                                                                    + submittedAsset.PositionsCreated.ElementAt(pos).PreEditPositionAccount.Trim().ToUpper());

                    return BadRequest("Asset-Position creation aborted due to error creating Position for : " 
                                                                    + submittedAsset.PositionsCreated.ElementAt(pos).PreEditPositionAccount.Trim().ToUpper());

                }
                
                submittedAsset.PositionsCreated.ElementAt(pos).CreatedPositionId = createdPosition.Content.PositionId; 
            }



            // INCOME (optional).
            if (!submittedAsset.RevenueCreated.Any()) 
                return ResponseMessage(new HttpResponseMessage {
                                              StatusCode = HttpStatusCode.Created,
                                              ReasonPhrase = "Asset created w/o submitted Income - affiliated Profile, and Position(s) recorded."
            });

            var incomeCtrl = new IncomeController(_identityService, _repository, _repositoryInvestor, _repositoryIncome);
            foreach (var incomeRecord in submittedAsset.RevenueCreated)
            {
                incomeRecord.Url = Utilities.GetBaseUrl(_repositoryInvestor.UrlAddress)
                                   + "Asset/"
                                   + submittedAsset.AssetTicker.Trim()
                                   + "/Income/";
               
                var createdIncome = await incomeCtrl.CreateNewIncome2(incomeRecord) as CreatedNegotiatedContentResult<Income>;
                if (createdIncome == null)
                    return BadRequest("Error creating new Income record(s). Please resubmit Income.");
            }

            return ResponseMessage(new HttpResponseMessage {
                StatusCode = HttpStatusCode.Created,
                ReasonPhrase = "Asset created - affiliated Profile, Position(s), and Income recorded."
            });

        }