public async Task <IEnumerable <SectionReference> > Handle(CreatePhysicalFixedPricedContractCommand request, CancellationToken cancellationToken)
        {
            List <SectionReference> sectionReferences = new List <SectionReference>();

            _unitOfWork.BeginTransaction();

            try
            {
                if (request.ContractReference?.Length > 0)
                {
                    request.ContractReference = request.ContractReference.PadLeft(7, '0');
                }

                var companyDate = await _systemDateTimeService.GetCompanyDate(request.CompanyId);

                if (request.ContractDate.Date > companyDate.Date)
                {
                    throw new AtlasBusinessException($"Contract date cannot be in the future. Contract date: {request.ContractDate.Date}. Company date: {companyDate}.");
                }

                if (request.DataVersionId != null)
                {
                    var freezeDate = await _freezeRepository.GetFreezeNotClosedAsync(request.CompanyId, request.DataVersionId.Value);

                    if (freezeDate == null)
                    {
                        throw new AtlasBusinessException($"Contracts cannot be created in a freeze if the month is closed.");
                    }

                    if (request.ContractReference == null)
                    {
                        throw new AtlasBusinessException($"Contract reference is mandatory in a frozen database.");
                    }
                }

                await PhysicalContractCommonRules.ValidatePhysicalContract(request, _identityService, _masterDataService, _userService, _systemDateTimeService);

                var user = _identityService.GetUserName();
                request.CreatedBy = user;
                var physicalFixedPricedContract = _mapper.Map <Section>(request);
                var company = await _masterDataService.GetCompanyByIdAsync(request.CompanyId);

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

                // At least one contract has to be always created
                physicalFixedPricedContract.NumberOfContract = (request.NumberOfContracts > 0) ? request.NumberOfContracts : 1;
                physicalFixedPricedContract.IsInterco        = request.IsInterco;

                if (!string.IsNullOrWhiteSpace(physicalFixedPricedContract.OtherReference))
                {
                    physicalFixedPricedContract.EstimatedMaturityDate = null;
                }

                physicalFixedPricedContract.EstimatedMaturityDate = await CalculateEstimatedMaturityDate(physicalFixedPricedContract, request.CompanyId);

                var references = (await _tradeRepository.CreatePhysicalContractAsImageAsync(physicalFixedPricedContract)).ToList();
                sectionReferences.AddRange(references);
                foreach (var item in references)
                {
                    if (item.SectionId > 0 && item.Quantity > 0 && physicalFixedPricedContract.Costs.Any())
                    {
                        foreach (var costItem in physicalFixedPricedContract.Costs)
                        {
                            costItem.CompanyId     = request.CompanyId;
                            costItem.SectionId     = item.SectionId;
                            costItem.DataVersionId = item.DataVersionId;
                        }

                        // check the business rule for PriceUnitId.
                        await _costRepository.AddCostsAsync(physicalFixedPricedContract.Costs, request.CompanyId, request.DataVersionId);
                    }

                    // request.ChildSections would not be null if only it is Imaging the trade and we have selected Image Splits/tranche option as well
                    if (request.ChildSections != null)
                    {
                        if (item.SectionId > 0 && request.ChildSections.Any())
                        {
                            CreateSplitCommand splitRequest = new CreateSplitCommand();
                            splitRequest.ChildSections = request.ChildSections;
                            splitRequest.ChildSections.ToList().ForEach(section => section.OriginalQuantity = 0);
                            splitRequest.CompanyId        = request.CompanyId;
                            splitRequest.OriginalQuantity = request.Quantity;
                            splitRequest.Quantity         = request.Quantity;
                            var sectionTrancheContract = _mapper.Map <SectionDeprecated>(splitRequest);
                            sectionTrancheContract.SectionId     = item.SectionId;
                            sectionTrancheContract.ContractLabel = item.ContractLabel;
                            foreach (var splitTrancheItem in sectionTrancheContract.ChildSections)
                            {
                                splitTrancheItem.SectionId             = 0;
                                splitTrancheItem.ContractId            = item.PhysicalContractId;
                                splitTrancheItem.SectionOriginId       = (int)item.SectionId;
                                splitTrancheItem.EstimatedMaturityDate = physicalFixedPricedContract.EstimatedMaturityDate;
                            }

                            bool isTradeImage          = true;
                            var  splitTranchReferences = await _tradeRepository.CreateTrancheSplitAsync(sectionTrancheContract, request.CompanyId, isTradeImage);

                            // Inserting cost while creating an Image of a trade,if available
                            foreach (var childItem in splitTranchReferences)
                            {
                                if (request.ChildSections.First().Costs != null)
                                {
                                    var childCosts = request.ChildSections.First().Costs;
                                    foreach (var costItem in childCosts)
                                    {
                                        costItem.CompanyId     = request.CompanyId;
                                        costItem.SectionId     = childItem.SectionId;
                                        costItem.DataVersionId = childItem.DataVersionId;
                                    }

                                    await _costRepository.AddCostsAsync(childCosts, request.CompanyId, request.DataVersionId);
                                }
                            }
                        }
                    }

                    if (request.IsInterco)
                    {
                        sectionReferences = await CreateIntercoContractOnCreateContract(request, physicalFixedPricedContract, references, sectionReferences);
                    }

                    if (request.DataVersionId != null)
                    {
                        // this might be incorrect. This is due to the code that is written above where you can create multiple contracts in your Current db with Image
                        await InsertFreezeRecalcProcessQueue(references[0].SectionId, request.DataVersionId, request.CompanyId);
                    }
                }

                _unitOfWork.Commit();
                _logger.LogInformation("New physical contract with id {Atlas_ContractLabel} created.", references[0].ContractLabel);

                return(sectionReferences);
            }
            catch
            {
                _unitOfWork.Rollback();
                throw;
            }
        }
        internal static async Task ValidatePhysicalContract(CreatePhysicalFixedPricedContractCommand command, IIdentityService identityService, IMasterDataService masterDataService, IUserService userService, ISystemDateTimeService systemDateTimeService)
        {
            // department
            var departments = await masterDataService.GetDepartmentsAsync(command.CompanyId);

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

            // trader
            if (command.TraderId != null)
            {
                var trader = await userService.GetUserByIdAsync(command.TraderId.Value);

                if (trader == null && !command.FieldsConfigurations.FirstOrDefault(field => field?.DisplayName == "TraderId").IsMandatory)
                {
                    throw new NotFoundException("User", command.TraderId);
                }
            }

            // counterparties - buyer and seller
            var counterparties = await masterDataService.GetCounterpartiesAsync(command.CompanyId);

            if (!counterparties.Any(c => c.CounterpartyCode == command.BuyerCode) && command.FieldsConfigurations.FirstOrDefault(field => field?.DisplayName == "BuyerId").IsMandatory)
            {
                throw new AtlasBusinessException($"The buyer {command.BuyerCode} does not belong to the {command.CompanyId} company.");
            }

            if (!counterparties.Any(c => c.CounterpartyCode == command.SellerCode) && command.FieldsConfigurations.FirstOrDefault(field => field?.DisplayName == "SellerId").IsMandatory)
            {
                throw new AtlasBusinessException($"The seller {command.SellerCode} does not belong to the {command.CompanyId} company.");
            }

            // commodity
            var commodities = await masterDataService.GetCommoditiesAsync(command.CompanyId);

            if (!commodities.Any(c => c.CommodityId == command.CommodityId) && command.FieldsConfigurations.FirstOrDefault(field => field?.DisplayName == "CommodityId").IsMandatory)
            {
                throw new AtlasBusinessException($"The commodity {command.CommodityId} does not belong to the {command.CompanyId} company.");
            }

            // quantity code
            var weightUnits = await masterDataService.GetWeightUnitsAsync(command.CompanyId);

            if (!weightUnits.Any(w => w.WeightUnitId == command.WeightUnitId) && command.FieldsConfigurations.DefaultIfEmpty().FirstOrDefault(field => field?.DisplayName == "WeightUnitId").IsMandatory)
            {
                throw new AtlasBusinessException($"The quantity code {command.WeightUnitId} does not belong to the {command.CompanyId} company.");
            }

            // contract term
            var contractTerms = await masterDataService.GetContractTermsAsync(command.CompanyId);

            if (!contractTerms.Any(c => c.ContractTermCode == command.ContractTerms) && command.FieldsConfigurations.FirstOrDefault(field => field?.DisplayName == "ContractTermId").IsMandatory)
            {
                throw new AtlasBusinessException($"The contract term {command.ContractTerms} does not belong to the {command.CompanyId} company.");
            }

            // port term
            var ports = await masterDataService.GetPortsAsync(command.CompanyId);

            if (!ports.Any(p => p.PortCode == command.ContractTermsLocation) && command.FieldsConfigurations.FirstOrDefault(field => field?.DisplayName == "ContractTermLocationId").IsMandatory)
            {
                throw new AtlasBusinessException($"The port term {command.ContractTermsLocation} does not belong to the {command.CompanyId} company.");
            }

            // port of origin
            if (command.PortOfOrigin != null)
            {
                if (!ports.Any(p => p.PortCode == command.PortOfOrigin))
                {
                    throw new AtlasBusinessException($"The port of origin {command.PortOfOrigin} does not belong to the {command.CompanyId} company.");
                }
            }

            // port of destination
            if (command.PortOfDestination != null)
            {
                if (!ports.Any(p => p.PortCode == command.PortOfDestination))
                {
                    throw new AtlasBusinessException($"The port of destination {command.PortOfDestination} does not belong to the {command.CompanyId} company.");
                }
            }

            // arbitration
            if (command.Arbitration != null)
            {
                var arbitrations = await masterDataService.GetArbitrationsAsync(command.CompanyId);

                if (!arbitrations.Any(a => a.ArbitrationCode == command.Arbitration))
                {
                    throw new AtlasBusinessException($"The arbitration {command.Arbitration} does not belong to the {command.CompanyId} company.");
                }
            }

            // currency
            var currencies = await masterDataService.GetCurrenciesAsync();

            if (!currencies.Any(c => c.CurrencyCode == command.CurrencyCode) && command.FieldsConfigurations.FirstOrDefault(field => field?.DisplayName == "CurrencyCode").IsMandatory)
            {
                throw new AtlasBusinessException($"The currency {command.CurrencyCode} does not belong to the {command.CompanyId} company.");
            }

            // price code
            var priceUnits = await masterDataService.GetPriceUnitsAsync(command.CompanyId);

            if (!priceUnits.Any(p => p.PriceUnitId == command.PriceUnitId) && command.FieldsConfigurations.FirstOrDefault(field => field?.DisplayName == "PricingMethodId").IsMandatory)
            {
                throw new AtlasBusinessException($"The price code {command.PriceUnitId} does not belong to the {command.CompanyId} company.");
            }

            // payment term
            var paymentTerms = await masterDataService.GetPaymentTermsAsync(command.CompanyId);

            if (!paymentTerms.Any(p => p.PaymentTermsCode == command.PaymentTerms) && command.FieldsConfigurations.FirstOrDefault(field => field?.DisplayName == "PaymentTermId").IsMandatory)
            {
                throw new AtlasBusinessException($"The payment term {command.PaymentTerms} does not belong to the {command.CompanyId} company.");
            }

            // period type
            var periodTypes = await masterDataService.GetPeriodTypesAsync(command.CompanyId);

            if (!periodTypes.Any(p => p.PeriodTypeId == command.PeriodTypeId) && command.FieldsConfigurations.FirstOrDefault(field => field?.DisplayName == "PeriodTypeId").IsMandatory)
            {
                throw new AtlasBusinessException($"The period type {command.PeriodTypeId} does not belong to the {command.CompanyId} company.");
            }
        }
        private async Task <List <SectionReference> > CreateIntercoContractOnCreateContract(CreatePhysicalFixedPricedContractCommand request,
                                                                                            Section physicalFixedPricedContract, List <SectionReference> references, List <SectionReference> sectionReferences)
        {
            // Create Interco Trade if available
            if (request.IsInterco)
            {
                string counterpartyCode = (physicalFixedPricedContract.Type == ContractType.Purchase) ?
                                          physicalFixedPricedContract.SellerCode : physicalFixedPricedContract.BuyerCode;
                var counterparty = await _masterDataService.GetAllByCounterpartyIdAsync(request.CompanyId, counterpartyCode);

                if (counterparty != null && counterparty.FirstOrDefault() != null &&
                    counterparty.FirstOrDefault().CompanyId != request.CompanyId &&
                    counterparty.FirstOrDefault().IsCounterpartyGroupAccount)
                {
                    var dataVersionId = await _systemDateTimeService.GetCompanyCurrentDataVersionId(request.IntercoCompanyId);

                    var intercoPhysicalFixedPricedContract = _mapper.Map <Section>(request);
                    intercoPhysicalFixedPricedContract.CompanyId     = physicalFixedPricedContract.IntercoCompanyId;
                    intercoPhysicalFixedPricedContract.TraderId      = physicalFixedPricedContract.IntercoTraderId;
                    intercoPhysicalFixedPricedContract.DepartmentId  = physicalFixedPricedContract.IntercoDepartmentId;
                    intercoPhysicalFixedPricedContract.Type          = (physicalFixedPricedContract.Type == ContractType.Purchase) ? ContractType.Sale : ContractType.Purchase;
                    intercoPhysicalFixedPricedContract.DataVersionId = dataVersionId;
                    intercoPhysicalFixedPricedContract.ContractDate  = DateTime.UtcNow;

                    intercoPhysicalFixedPricedContract.Costs = physicalFixedPricedContract.Costs.Where(r => r.SupplierCode == counterpartyCode);

                    // At least one contract has to be always created
                    intercoPhysicalFixedPricedContract.NumberOfContract = 1;

                    var intercoReferences = (await _tradeRepository.CreatePhysicalContractAsImageAsync(intercoPhysicalFixedPricedContract)).ToList();

                    foreach (var intercoItem in intercoReferences)
                    {
                        if (intercoItem.SectionId > 0 && intercoPhysicalFixedPricedContract.Costs.Any())
                        {
                            foreach (var intercoCostItem in intercoPhysicalFixedPricedContract.Costs)
                            {
                                intercoCostItem.CompanyId       = intercoPhysicalFixedPricedContract.CompanyId;
                                intercoCostItem.SectionId       = intercoItem.SectionId;
                                intercoCostItem.DataVersionId   = dataVersionId;
                                intercoCostItem.CostDirectionId = (intercoCostItem.CostDirectionId == 1) ? 2 : 1;
                            }

                            // check the business rule for PriceUnitId.
                            await _costRepository.AddCostsAsync(intercoPhysicalFixedPricedContract.Costs, intercoPhysicalFixedPricedContract.CompanyId, dataVersionId);
                        }
                    }

                    // Update Reference & Memo Details
                    var sourceDataVersionId = await _systemDateTimeService.GetCompanyCurrentDataVersionId(physicalFixedPricedContract.CompanyId);

                    await UpdateReferenceAndInternalMemo(sourceDataVersionId,
                                                         references.FirstOrDefault().PhysicalContractId,
                                                         request.IntercoCompanyId.ToUpper() + "/" + intercoReferences.FirstOrDefault().ContractLabel,
                                                         dataVersionId,
                                                         intercoReferences.FirstOrDefault().PhysicalContractId,
                                                         request.CompanyId.ToUpper() + "/" + references.FirstOrDefault().ContractLabel,
                                                         request.Type);

                    sectionReferences.AddRange(intercoReferences);
                }
                else
                {
                    throw new AtlasBusinessException($"Invalid Counterparty for Interco Contract.");
                }
            }
            return(sectionReferences);
        }