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; } }
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; } }