/// <inheritdoc/>
        public async Task <UpdatedContractStatusResponse> WithdrawalAsync(UpdateContractWithdrawalRequest request)
        {
            _logger.LogInformation($"[{nameof(WithdrawalAsync)}] called with contract number: {request.ContractNumber} and contract version {request.ContractVersion}.");

            var contract = await _repository.GetByContractNumberAndVersionWithIncludesAsync(request.ContractNumber, request.ContractVersion, ContractDataEntityInclude.Datas);

            ContractStatus newContractStatus = request.WithdrawalType;

            _contractValidator.Validate(contract, request);
            _contractValidator.ValidateStatusChange(contract, newContractStatus);

            var updatedContractStatusResponse = new UpdatedContractStatusResponse
            {
                Id              = contract.Id,
                ContractNumber  = contract.ContractNumber,
                ContractVersion = contract.ContractVersion,
                Ukprn           = contract.Ukprn,
                Status          = (ContractStatus)contract.Status,
                Action          = ActionType.ContractWithdrawal
            };

            contract.Status = (int)newContractStatus;

            await _contractDocumentService.UpsertOriginalContractXmlAsync(contract, request);

            await _repository.UpdateContractAsync(contract);

            updatedContractStatusResponse.NewStatus = (ContractStatus)contract.Status;

            await _mediator.Publish(updatedContractStatusResponse);

            return(updatedContractStatusResponse);
        }
        private AuditModels.Audit GetAudit(UpdatedContractStatusResponse updatedContractStatusResponse)
        {
            string oldStatusName = updatedContractStatusResponse.Status.ToString("G");
            string newStatusName = updatedContractStatusResponse.NewStatus.ToString("G");

            string message = $"Contract [{updatedContractStatusResponse.ContractNumber}] Version number [{updatedContractStatusResponse.ContractVersion}] with Id [{updatedContractStatusResponse.Id}] has been {newStatusName}. Additional Information Details: ContractId is: {updatedContractStatusResponse.Id}. Contract Status Before was {oldStatusName} . Contract Status After is {newStatusName}";

            return(new AuditModels.Audit()
            {
                Action = ActionType.ContractConfirmApproval,
                Severity = SeverityLevel.Information,
                Ukprn = updatedContractStatusResponse.Ukprn,
                Message = message,
                User = $"[{_appName}]"
            });
        }
        /// <inheritdoc/>
        public async Task <UpdatedContractStatusResponse> ApproveManuallyAsync(ContractRequest request)
        {
            _logger.LogInformation($"[{nameof(ApproveManuallyAsync)}] called with contract number: {request.ContractNumber} and contract version {request.ContractVersion}.");
            UpdatedContractStatusResponse updatedContractStatusResponse = null;

            var manuallyApproved  = true;
            var newContractStatus = ContractStatus.Approved;

            var contract = await _repository.GetByContractNumberAndVersionWithIncludesAsync(request.ContractNumber, request.ContractVersion, ContractDataEntityInclude.Datas | ContractDataEntityInclude.Content);

            _contractValidator.Validate(contract, request, c => c.ContractContent != null);
            _contractValidator.ValidateStatusChange(contract, newContractStatus, manuallyApproved);

            updatedContractStatusResponse = new UpdatedContractStatusResponse
            {
                Id              = contract.Id,
                ContractNumber  = contract.ContractNumber,
                ContractVersion = contract.ContractVersion,
                Ukprn           = contract.Ukprn,
                Status          = (ContractStatus)contract.Status,
                Action          = ActionType.ContractManualApproval
            };

            var contractRefernce       = contract.ContractContent.FileName.Replace(".pdf", string.Empty);
            var signer                 = $"hand and approved by ESFA";
            var updatedDate            = DateTime.UtcNow;
            var signedContractDocument = _documentService.AddSignedDocumentPage(contract.ContractContent.Content, contractRefernce, signer, updatedDate, manuallyApproved, (ContractFundingType)contract.FundingType);

            contract.ContractContent.Content = signedContractDocument;
            contract.ContractContent.Size    = signedContractDocument.Length;

            contract.Status              = (int)newContractStatus;
            contract.SignedOn            = updatedDate;
            contract.SignedBy            = signer;
            contract.SignedByDisplayName = signer;
            contract.WasManuallyApproved = manuallyApproved;

            await _contractDocumentService.UpsertOriginalContractXmlAsync(contract, request);

            await _repository.UpdateContractAsync(contract);

            updatedContractStatusResponse.NewStatus = (ContractStatus)contract.Status;

            await _mediator.Publish(updatedContractStatusResponse);

            return(updatedContractStatusResponse);
        }
        /// <inheritdoc/>
        public async Task <UpdatedContractStatusResponse> UpdateContractStatusAsync(int contractId, ContractStatus requiredContractStatus, ContractStatus newContractStatus)
        {
            UpdatedContractStatusResponse updatedContractStatusResponse = null;
            var updatedDate = DateTime.UtcNow;
            var contract    = await _repository.GetByIdAsync(contractId);

            if (contract != null)
            {
                updatedContractStatusResponse = new UpdatedContractStatusResponse()
                {
                    Id = contract.Id, ContractNumber = contract.ContractNumber, ContractVersion = contract.ContractVersion, Ukprn = contract.Ukprn, Status = (ContractStatus)contract.Status
                };

                if (contract.Status == (int)requiredContractStatus)
                {
                    contract.Status        = (int)newContractStatus;
                    contract.LastUpdatedAt = updatedDate;
                    await _work.CommitAsync();

                    updatedContractStatusResponse.NewStatus = (ContractStatus)contract.Status;
                    _logger.LogInformation($"[{nameof(UpdateContractStatusAsync)}] - Updated successfully the contract status to {(ContractStatus)contract.Status} - Contract Id: {contractId}, Contract Number: {contract.ContractNumber}");
                }
                else
                {
                    _logger.LogError($"[[{nameof(UpdateContractStatusAsync)}] Contract status is not {requiredContractStatus} - Contract Id {contractId} , the current status is {(ContractStatus)contract.Status}.");
                    throw new ContractStatusException($"Contract status is not {requiredContractStatus} - Contract Id {contractId} , the current status is {(ContractStatus)contract.Status}.");
                }
            }
            else
            {
                _logger.LogError($"[[{nameof(UpdateContractStatusAsync)}] Contract not found - Contract Id {contractId}.");
                throw new ContractNotFoundException($"Contract not found - Contract Id {contractId}.");
            }

            return(updatedContractStatusResponse);
        }
        /// <inheritdoc/>
        public async Task CreateAsync(CreateContractRequest request)
        {
            await _semaphoreOnEntity.WaitAsync(request.ContractNumber).ConfigureAwait(false);

            try
            {
                _logger.LogInformation($"[{nameof(CreateAsync)}] Creating new contract [{request.ContractNumber}] version [{request.ContractVersion}] for [{request.UKPRN}].");

                var existing = await _repository.GetByContractNumberAsync(request.ContractNumber);

                _contractValidator.ValidateForNewContract(request, existing);

                var newContract = _mapper.Map <Repository.DataModels.Contract>(request);
                newContract.LastUpdatedAt = newContract.CreatedAt = DateTime.UtcNow;

                // For amendment type notification the default status has to be approved
                // For None and Variation, it should be published to provider
                if (request.AmendmentType == ContractAmendmentType.Notfication)
                {
                    newContract.Status              = (int)ContractStatus.Approved;
                    newContract.SignedOn            = request.SignedOn.Value.Date;
                    newContract.SignedBy            = "Feed";
                    newContract.SignedByDisplayName = "Feed";
                }
                else if (request.AmendmentType == ContractAmendmentType.None || request.AmendmentType == ContractAmendmentType.Variation)
                {
                    newContract.Status = (int)ContractStatus.PublishedToProvider;
                }

                await _contractDocumentService.UpsertOriginalContractXmlAsync(newContract, new ContractRequest()
                {
                    FileName = request.ContractData, ContractNumber = request.ContractNumber, ContractVersion = request.ContractVersion
                });

                await _repository.CreateAsync(newContract);

                var updatedContractStatusResponse = new UpdatedContractStatusResponse
                {
                    Id              = newContract.Id,
                    ContractNumber  = newContract.ContractNumber,
                    ContractVersion = newContract.ContractVersion,
                    Ukprn           = newContract.Ukprn,
                    NewStatus       = (ContractStatus)newContract.Status,
                    Action          = ActionType.ContractCreated,
                    AmendmentType   = request.AmendmentType
                };

                _logger.LogInformation($"[{nameof(CreateAsync)}] Contract [{newContract.ContractNumber}] version [{newContract.ContractVersion}] has been created for [{newContract.Ukprn}].");

                // Update operations to existing records can be done outside the semaphore
                if (request.AmendmentType == ContractAmendmentType.Variation || request.AmendmentType == ContractAmendmentType.None)
                {
                    var statuses = new int[]
                    {
                        (int)ContractStatus.PublishedToProvider
                    };

                    await ReplaceContractsWithGivenStatuses(existing, statuses);
                }
                else if (request.AmendmentType == ContractAmendmentType.Notfication)
                {
                    var statuses = new int[]
                    {
                        (int)ContractStatus.Approved,
                        (int)ContractStatus.ApprovedWaitingConfirmation,
                        (int)ContractStatus.PublishedToProvider
                    };

                    await ReplaceContractsWithGivenStatuses(existing, statuses);
                }

                await _mediator.Publish(updatedContractStatusResponse);
            }
            finally
            {
                _semaphoreOnEntity.Release(request.ContractNumber);
            }
        }
 private void ForMemberFix(UpdatedContractStatusResponse src, ContractNotification dest)
 {
     dest.Status = src.NewStatus;
 }