コード例 #1
0
ファイル: FxDealRepository.cs プロジェクト: mrsunil/bp2
        public async Task UpdateFxDealAsync(FxDeal fxDeal, string company)
        {
            var queryParameters = new DynamicParameters();

            queryParameters.Add("@iCompanyId", company);
            queryParameters.Add("@iFxDeals", ConvertToFxDealUDTT(new[] { fxDeal }));
            queryParameters.Add("@iDataVersionId", null);

            await ExecuteNonQueryAsync(StoredProcedureNames.UpdateFxDeals, queryParameters, true);
        }
コード例 #2
0
ファイル: FxDealRepository.cs プロジェクト: mrsunil/bp2
        public async Task <FxDealReference> CreateFxDealAsync(FxDeal fxDeal, string company)
        {
            var queryParameters = new DynamicParameters();

            queryParameters.Add("@iCompanyId", company);
            queryParameters.Add("@iFxDeals", ConvertToFxDealUDTT(new[] { fxDeal }));
            queryParameters.Add("@iDataVersionId", null);

            var result = await ExecuteQueryFirstOrDefaultAsync <FxDealReference>(StoredProcedureNames.CreateFxDeals, queryParameters, true);

            return(result);
        }
コード例 #3
0
        public async Task <Unit> Handle(DeleteFxDealCommand request, CancellationToken cancellationToken)
        {
            _unitOfWork.BeginTransaction();
            try
            {
                // Load fx deal from DB
                FxDeal fxDeal = new FxDeal {
                    FxDealStatusId = (int)FxDealStatus.Open
                };

                if (fxDeal == null)
                {
                    throw new NotFoundException("fxDeal", request.FxDealId);
                }

                // Check fx deal status
                if (fxDeal.FxDealStatusId == (int)FxDealStatus.Open ||
                    (fxDeal.FxDealStatusId == (int)FxDealStatus.Settled && !fxDeal.Sections.Any()))
                {
                    await _fxDealRepository.DeleteFxDealAsync(request.FxDealId, request.Company);

                    if (fxDeal.FxDealStatusId == (int)FxDealStatus.Settled)
                    {
                        _logger.LogWarning("Settled Fx deal with id {Atlas_FxDealId} deleted.", request.FxDealId);
                    }
                    else
                    {
                        _logger.LogInformation("Fx deal with id {Atlas_FxDealId} deleted.", request.FxDealId);
                    }

                    _unitOfWork.Commit();
                }
                else
                {
                    throw new AtlasBusinessException("This Fx deal cannot be deleted.");
                }
            }
            catch
            {
                _unitOfWork.Rollback();
                throw;
            }

            return(Unit.Value);
        }
コード例 #4
0
        public async Task <Unit> Handle(UpdateFxDealSectionsCommand request, CancellationToken cancellationToken)
        {
            _unitOfWork.BeginTransaction();
            try
            {
                // Load fx deal from DB
                var fxDealDto = await _fxDealQueries.GetFxDealByIdAsync(request.FxDealId, request.CompanyId);

                if (fxDealDto == null)
                {
                    throw new NotFoundException("fxDeal", request.FxDealId);
                }

                FxDeal fxDealToUpdate = new FxDeal {
                    FxDealId = request.FxDealId, FxDealStatusId = fxDealDto.FxDealStatusId, CurrencyCode = fxDealDto.CurrencyCode, DepartmentId = fxDealDto.DepartmentId, Sections = new List <Entities.FxDealSection>()
                };

                // Check fx deal status
                if (fxDealDto.FxDealStatusId == (int)FxDealStatus.Open || fxDealDto.FxDealStatusId == (int)FxDealStatus.Linked)
                {
                    // Match existing section with updated ones
                    var matchedSections =
                        (from ori in fxDealDto.Sections
                         join upd in request.Sections on ori.SectionId equals upd.SectionId into updatedSections
                         from s in updatedSections
                         select new
                    {
                        OriginalSection = ori,
                        UpdatedSection = s,
                    }).ToList();

                    // Update existing section with new values
                    foreach (var item in matchedSections)
                    {
                        fxDealToUpdate.Sections.Add(new Entities.FxDealSection
                        {
                            SectionId       = item.OriginalSection.SectionId,
                            CoverApplied    = item.UpdatedSection.CoverApplied,
                            UncoveredAmount = item.OriginalSection.UncoveredAmount
                        });

                        item.OriginalSection.CoverApplied = item.UpdatedSection.CoverApplied;
                    }

                    // List of sections added (sections from request that do not match existing ones)
                    var addedSections = request.Sections.Except(matchedSections.Select(s => s.UpdatedSection)).ToList();

                    // If new sections have been added
                    if (addedSections.Any())
                    {
                        // Load information about the new sections
                        IEnumerable <SectionInformationFxDeal> sectionInfo = await _fxDealRepository.GetSectionInformationForFxDealAsync(addedSections.Select(s => s.SectionId), request.CompanyId);

                        // Check if new sections can be associated to the fx deal (same currency, same department)
                        if (sectionInfo.Any(s => s.CurrencyCode != fxDealToUpdate.CurrencyCode))
                        {
                            throw new AtlasBusinessException($"The associated sections must have the same currency as the fx deal ({fxDealDto.CurrencyCode}).");
                        }

                        if (sectionInfo.Any(s => s.DepartmentId != fxDealToUpdate.DepartmentId))
                        {
                            throw new AtlasBusinessException($"The associated sections must have the same department as the fx deal.");
                        }

                        // Match added section with information from DB
                        var matchedAddedSections =
                            (from a in addedSections
                             join s in sectionInfo on a.SectionId equals s.SectionId into sectionsInfo
                             from si in sectionsInfo.DefaultIfEmpty() // DefaultIfEmpty preserves left-hand elements that have no matches on the right side
                             select new
                        {
                            AddedSection = a,
                            SectionInformation = si,
                        }).ToList();

                        // Associate the new sections to fx deal
                        foreach (var item in matchedAddedSections)
                        {
                            if (item.SectionInformation == null)
                            {
                                throw new AtlasBusinessException($"Cannot found section {item.AddedSection.SectionId}.");
                            }

                            fxDealToUpdate.Sections.Add(
                                new Entities.FxDealSection
                            {
                                SectionId       = item.AddedSection.SectionId,
                                CoverApplied    = item.AddedSection.CoverApplied,
                                UncoveredAmount = item.SectionInformation.UncoveredAmount
                            });
                        }
                    }

                    // A control must be applied on the "Cover applied" field to prevent the user to enter a value higher than “Amount uncovered” field’s value.
                    foreach (var section in fxDealToUpdate.Sections)
                    {
                        if (section.CoverApplied > section.UncoveredAmount)
                        {
                            throw new AtlasBusinessException($"The cover applied ({section.CoverApplied}) of the physical trade {section.SectionId} cannot be greather that the amount uncovered ({section.UncoveredAmount}).");
                        }
                    }

                    var totalCoverApplied = fxDealDto.Sections.Sum(s => s.CoverApplied);
                    if (fxDealDto.Amount < totalCoverApplied)
                    {
                        throw new AtlasBusinessException("The sum of the amount of the physical trade covered by the FX deal cannot be greather that the dealt amount.");
                    }

                    // Update fx deal status to Linked
                    if (fxDealDto.Sections.Any() || fxDealToUpdate.Sections.Any())
                    {
                        fxDealToUpdate.FxDealStatusId = (int)FxDealStatus.Linked;
                    }

                    //await _fxDealRepository.UpdateFxDealAsync(fxDeal, request.CompanyId);

                    await _fxDealRepository.UpdateFxDealSectionsAsync(fxDealDto.FxDealId, fxDealToUpdate.Sections, request.CompanyId);

                    _logger.LogInformation("Fx deal with id {Atlas_FxDealId} updated.", fxDealDto.FxDealId);

                    _unitOfWork.Commit();
                }
                else
                {
                    throw new AtlasBusinessException("This Fx deal is not editable.");
                }

                return(Unit.Value);
            }
            catch
            {
                _unitOfWork.Rollback();
                throw;
            }
        }
コード例 #5
0
ファイル: FxDealCommonRules.cs プロジェクト: mrsunil/bp2
        internal static async Task ValidateFxDeal(FxDeal fxDeal, IIdentityService identityService, IMasterDataService masterDataService, IUserService userService, ISystemDateTimeService systemDateTimeService)
        {
            var departments = await masterDataService.GetDepartmentsAsync(fxDeal.CompanyId);

            if (!departments.Any(d => d.DepartmentId == fxDeal.DepartmentId))
            {
                throw new AtlasBusinessException($"The department {fxDeal.DepartmentId} does not belong to the {fxDeal.CompanyId} company.");
            }

            var trader = await userService.GetUserByIdAsync(fxDeal.TraderId);

            if (trader == null)
            {
                throw new NotFoundException("User", fxDeal.TraderId);
            }

            if (!trader.Permissions.Any(p => p.CompanyId == fxDeal.CompanyId && p.IsTrader))
            {
                throw new AtlasBusinessException($"The user {fxDeal.TraderId} is not configured as a trader for company {fxDeal.CompanyId}.");
            }

            var companyDate = await systemDateTimeService.GetCompanyDate(fxDeal.CompanyId);

            // The date entered in the Contract date field by the user is not in the future.
            if (fxDeal.ContractDate.Date > companyDate.Date)
            {
                throw new AtlasBusinessException($"The contract date cannot be in the future. Company date: {companyDate.Date}");
            }

            // The department code must belong to the list of departments attached to the user’s account.
            var user = await userService.GetUserByIdAsync(identityService.GetUserAtlasId());

            var companyPermissions = user.Permissions
                                     .FirstOrDefault(p => p.CompanyId == fxDeal.CompanyId);

            var userDepartments = companyPermissions.Departments
                                  .Select(department => department.DepartmentId).ToList();

            if (!companyPermissions.AllDepartments && !userDepartments.Contains(fxDeal.DepartmentId))
            {
                throw new AtlasBusinessException($"The department {fxDeal.DepartmentId} does not belong to the list of departments attached to the user’s account.");
            }

            // The FX Deal type must belong to the Deal type master data
            var fxTradeTypes = await masterDataService.GetFxTradeTypes(fxDeal.CompanyId);

            if (!fxTradeTypes.Any(n => n.FxTradeTypeId == fxDeal.FxTradeTypeId))
            {
                throw new AtlasBusinessException($"The FX Deal type {fxDeal.FxTradeTypeId} does not belong to the company {fxDeal.CompanyId}.");
            }

            // Settled amount calculation
            // The value is calculated by multiplying or dividing (depending on M/D field) the “Dealt amount” field’s value by the “Spot ROE” field’s value.
            var settledAmount = fxDeal.Amount * (fxDeal.SpotRateType == "D" ? 1 / fxDeal.SpotRate : fxDeal.SpotRate);

            // TODO: tolerance band on Spot ROE

            // Traded ROE field is the sum of the “Spot ROE” and “FW Points”
            var tradedRoe = fxDeal.SpotRate + fxDeal.FwPoints;

            // The Nominal account (Deal) must belong to the Nominal account master data assigned to the company.
            var nominalAccounts = await masterDataService.GetNominalAccountsAsync(fxDeal.CompanyId);

            if (!nominalAccounts.Any(n => n.NominalAccountId == fxDeal.NominalAccountId))
            {
                throw new AtlasBusinessException($"The Nominal account (Deal) {fxDeal.NominalAccountId} does not belong to the company {fxDeal.CompanyId}.");
            }

            // The Nominal account (Settlement) must belong to the Nominal account master data assigned to the company.
            if (!nominalAccounts.Any(n => n.NominalAccountId == fxDeal.SettlementNominalAccountId))
            {
                throw new AtlasBusinessException($"The Nominal account (Settlement) {fxDeal.NominalAccountId} does not belong to the company {fxDeal.CompanyId}.");
            }

            // The Bank/broker” must belong to the the list of counterparties assigned to the company and having the value “Bank” in “Account type” field
            var counterparties = await masterDataService.GetCounterpartiesAsync(fxDeal.CompanyId);

            if (!counterparties.Any(c => c.CounterpartyID == fxDeal.CounterpartyId))
            {
                throw new AtlasBusinessException($"The counterparty {fxDeal.CounterpartyId} does not belong to the company {fxDeal.CounterpartyId}.");
            }
        }