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;
            }
        }
Esempio n. 2
0
        public async Task <Unit> Handle(UpdateFxDealCommand request, CancellationToken cancellationToken)
        {
            _unitOfWork.BeginTransaction();
            try
            {
                var fxDealToUpdate = _mapper.Map <FxDeal>(request);
                var company        = await _masterDataService.GetCompanyByIdAsync(request.CompanyId);

                if (company.IsProvinceEnable)
                {
                    fxDealToUpdate.ProvinceId = company.DefaultProvinceId;
                    fxDealToUpdate.BranchId   = company.DefaultBranchId;
                }
                else
                {
                    fxDealToUpdate.ProvinceId = null;
                    fxDealToUpdate.BranchId   = null;
                }

                IEnumerable <MasterData.Common.Entities.FxTradeType> fxTradeType = await _masterDataService.GetFxTradeTypes(fxDealToUpdate.CompanyId);

                if (fxDealToUpdate.FxTradeTypeId != null)
                {
                    var objectFxTradeType = fxTradeType.FirstOrDefault(x => x.FxTradeTypeId == fxDealToUpdate.FxTradeTypeId);

                    if (!objectFxTradeType.IsNdf)
                    {
                        fxDealToUpdate.NdfAgreedDate = null;
                        fxDealToUpdate.NdfAgreedRate = null;
                    }
                }
                else
                {
                    fxDealToUpdate.NdfAgreedDate = null;
                    fxDealToUpdate.NdfAgreedRate = null;
                }


                // Load fx deal from DB
                var fxDealDto = await _fxDealQueries.GetFxDealByIdAsync(request.FxDealId, request.CompanyId);

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

                // Check fx deal status
                //if (fxDealDto.FxDealStatusId != (int)FxDealStatus.Open || fxDealDto.Sections.Any())
                //{
                //    throw new AtlasBusinessException("This Fx deal is not editable.");
                //}

                if (fxDealDto.FxDealStatusId != (int)FxDealStatus.Open && fxDealDto.FxDealStatusId != (int)FxDealStatus.Linked)
                {
                    throw new AtlasBusinessException("This Fx deal is not editable.");
                }

                // Update fx deal (only when status is open)
                if (fxDealDto.FxDealStatusId == (int)FxDealStatus.Open)
                {
                    // Validate business rules
                    //await FxDealCommonRules.ValidateFxDeal(fxDealToUpdate, _identityService, _masterDataService, _userService, _systemDateTimeService);

                    fxDealToUpdate.FxDealStatusId = fxDealDto.FxDealStatusId;
                    if (fxDealDto.Sections.Any() || fxDealToUpdate.Sections.Any())
                    {
                        fxDealToUpdate.FxDealStatusId = (int)FxDealStatus.Linked;
                    }

                    await _fxDealRepository.UpdateFxDealAsync(fxDealToUpdate, request.CompanyId);
                }

                // Update associated sections
                if (fxDealToUpdate.Sections.Any())
                {
                    // Match existing section with updated ones
                    var matchedSections =
                        (from ori in fxDealDto.Sections
                         join upd in fxDealToUpdate.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)
                    {
                        item.UpdatedSection.UncoveredAmount = item.OriginalSection.UncoveredAmount;
                        //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 = fxDealToUpdate.Sections.Except(matchedSections.Select(s => s.UpdatedSection)).ToList();

                    // If new sections have been added
                    if (addedSections.Any())
                    {
                        // Load information about the new sections
                        var 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 ({fxDealToUpdate.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}.");
                            }

                            item.AddedSection.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}).");
                        }
                    }

                    // CoverApplied of existing sections (after update)
                    var allCoverApplied =
                        (from a in fxDealDto.Sections
                         join b in fxDealToUpdate.Sections on a.SectionId equals b.SectionId into su
                         from s in su.DefaultIfEmpty() // DefaultIfEmpty preserves left-hand elements that have no matches on the right side
                         select s?.CoverApplied ?? a.CoverApplied).ToList();

                    // Sum of the cover applied of all associated sections (after update)
                    var totalCoverApplied = addedSections.Sum(s => s.CoverApplied) + allCoverApplied.Sum();
                    if (fxDealToUpdate.Amount < totalCoverApplied)
                    {
                        throw new AtlasBusinessException($"The sum of the amount of the physical trade covered by the FX deal ({totalCoverApplied}) cannot be greather that the dealt amount ({fxDealToUpdate.Amount}).");
                    }

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

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

                _unitOfWork.Commit();

                return(Unit.Value);
            }
            catch
            {
                _unitOfWork.Rollback();
                throw;
            }
        }