private ProposalResult Update(FixedPriceProposal proposal, bool commit = true, bool fireEvents = true) { _logger.LogInformation(GetLogMessage("Proposal:{0}"), proposal.Id); _logger.LogInformation(GetLogMessage("Proposal story Point basis : {0}"), proposal.StoryPointBasis); _logger.LogInformation(GetLogMessage("Proposal estimation basis : {0}"), proposal.EstimationBasis); _logger.LogInformation(GetLogMessage("Proposal customer rate basis : {0}"), proposal.CustomerRateBasis); _logger.LogInformation(GetLogMessage("Proposal other percent basis : {0}"), proposal.OtherPercentBasis); _logger.LogInformation(GetLogMessage("Proposal total hours : {0}"), proposal.TotalHours); _logger.LogInformation(GetLogMessage("Proposal total price quoted : {0}"), proposal.TotalPriceQuoted); var retVal = new ProposalResult() { ProposalId = proposal.Id }; proposal.UpdatedById = _userInfo.UserId; proposal.Updated = DateTimeOffset.UtcNow; proposal.ObjectState = ObjectState.Modified; var records = Repository.InsertOrUpdateGraph(proposal, commit); _logger.LogDebug(GetLogMessage("{0} records updated"), records); if (records > 0) { retVal.Succeeded = true; } return(retVal); }
private async Task <ProposalResult> RevokeProposal(FixedPriceProposal proposal) { _logger.LogInformation(GetLogMessage("Proposal: {0}"), proposal.Id); var retVal = new ProposalResult() { ProposalId = proposal.Id }; proposal.UpdatedById = _userInfo.UserId; proposal.Updated = DateTimeOffset.UtcNow; proposal.ObjectState = ObjectState.Modified; proposal.Status = ProposalStatus.Draft; proposal.StatusTransitions.Add(new ProposalStatusTransition() { Status = ProposalStatus.Draft, ObjectState = ObjectState.Added }); var result = Repository.Update(proposal, true); _logger.LogDebug(GetLogMessage("Records updated: {0}"), result); if (result > 0) { retVal.Succeeded = true; } return(retVal); }
private async Task <ProposalResult> SendProposal(FixedPriceProposal proposal) { _logger.LogInformation(GetLogMessage("Sending Proposal: {0}"), proposal.Id); var retVal = new ProposalResult { ProposalId = proposal.Id }; if (proposal == null) { retVal.ErrorMessage = "Proposal does not exist"; return(retVal); } if (proposal.Status != ProposalStatus.Pending) { _logger.LogDebug(GetLogMessage("Proposal ready to be sent")); proposal.Status = ProposalStatus.Pending; proposal.StatusTransitions.Add(new ProposalStatusTransition() { Status = ProposalStatus.Pending, ObjectState = ObjectState.Added }); proposal.UpdatedById = _userInfo.UserId; proposal.Updated = DateTimeOffset.UtcNow; proposal.ObjectState = ObjectState.Modified; var records = Repository.Update(proposal, true); _logger.LogDebug("{0} records updated in database"); if (records > 0) { retVal.Succeeded = true; await Task.Run(() => { RaiseEvent(new ProposalSentEvent() { ProposalId = proposal.Id }); }); } } return(retVal); }
private async Task <bool> DeleteProposal(FixedPriceProposal proposal) { bool retVal = false; if (proposal?.ProposalAcceptance != null) { throw new ApplicationException("You cannot delete a proposal that's been accepted"); } if (proposal != null) { retVal = await Repository.DeleteAsync(proposal, true); } return(retVal); }
private async Task <ProposalResult> RejectProposal(FixedPriceProposal proposal, ProposalRejectionInput input) { if (proposal == null) { throw new ApplicationException("No proposal found with this id for this organization"); } var retVal = new ProposalResult() { ProposalId = proposal.Id }; proposal.Status = ProposalStatus.Rejected; proposal.UpdatedById = _userInfo.UserId; proposal.Updated = DateTimeOffset.UtcNow; proposal.StatusTransitions.Add(new ProposalStatusTransition() { Status = ProposalStatus.Rejected, ObjectState = ObjectState.Added }); proposal.InjectFrom(input); var result = Update(proposal); if (result.Succeeded) { retVal.Succeeded = true; await Task.Run(() => { RaiseEvent(new ProposalRejectedEvent { ProposalId = result.ProposalId }); }); } return(retVal); }
private async Task <ProposalResult> AcceptFixedPriceProposal(FixedPriceProposal proposal) { var retVal = new ProposalResult() { ProposalId = proposal.Id }; if (proposal.Status == ProposalStatus.Accepted && proposal.ProposalAcceptance != null) { retVal.ErrorMessage = "Proposal is already accepted"; return(retVal); } var now = DateTimeOffset.UtcNow; proposal.Status = ProposalStatus.Accepted; proposal.UpdatedById = _userInfo.UserId; proposal.Updated = now; proposal.ObjectState = ObjectState.Modified; proposal.Project.Status = ProjectStatus.Active; proposal.Project.ObjectState = ObjectState.Modified; proposal.Project.Updated = now; proposal.Project.UpdatedById = _userInfo.UserId; proposal.StatusTransitions.Add(new ProposalStatusTransition() { Status = ProposalStatus.Accepted, ObjectState = ObjectState.Added }); foreach (var contract in proposal.Project.Contracts.Where(x => x.Status == ContractStatus.Pending)) { contract.Status = ContractStatus.Active; contract.ObjectState = ObjectState.Modified; contract.UpdatedById = _userInfo.UserId; contract.Updated = now; contract.StatusTransitions.Add(new ContractStatusTransition() { ObjectState = ObjectState.Added, Status = ContractStatus.Active }); } proposal.ProposalAcceptance = new ProposalAcceptance() { Created = now, AcceptedCompletionDate = DateTimeOffset.UtcNow.Date .AddDays(Convert.ToDouble(proposal.TotalDays)) .Date, TotalCost = proposal.TotalPriceQuoted, CustomerRate = proposal.CustomerRateBasis, NetTerms = 7, // todo: fix this ProposalType = proposal.ProposalType, TotalDays = proposal.TotalDays, Velocity = proposal.VelocityBasis, AgreementText = proposal.AgreementText, Updated = now, CustomerId = proposal.Project.CustomerId, CustomerOrganizationId = proposal.Project.CustomerOrganizationId, AcceptedBy = _userInfo.UserId, ProposalBlob = string.Empty, ObjectState = ObjectState.Added }; foreach (var story in proposal.Project.Stories.Where(x => x.Status == StoryStatus.Pending)) { story.CustomerAcceptanceDate = now; story.Updated = now; story.ObjectState = ObjectState.Modified; story.Status = StoryStatus.Approved; story.CustomerApprovedHours = story.StoryPoints * proposal.EstimationBasis; story.StatusTransitions.Add(new StoryStatusTransition() { Status = StoryStatus.Approved, ObjectState = ObjectState.Added }); _logger.LogDebug(GetLogMessage("Setting approved story hours for story: {0}, amount: {1}"), story.Id, story.CustomerApprovedHours); } var proposalResult = Repository.InsertOrUpdateGraph(proposal, true); _logger.LogDebug(GetLogMessage("{0} records updated"), proposalResult); if (proposalResult > 0) { retVal.Succeeded = true; await Task.Run(() => { RaiseEvent(new ProposalAcceptedEvent() { ProposalId = proposal.Id }); }); foreach (var contract in proposal.Project.Contracts.Where(x => x.Updated == now)) { await Task.Run(() => { RaiseEvent(new ContractApprovedEvent() { ContractId = contract.Id }); }); } foreach (var story in proposal.Project.Stories.Where(x => x.Updated == now)) { await Task.Run(() => { RaiseEvent(new StoryApprovedEvent() { StoryId = story.Id }); }); } } return(retVal); }
private async Task <ProposalResult> Create(ProposalOptions input, Guid projectId, Guid organizationId) { _logger.LogInformation(GetLogMessage($@"Create Proposal Proposal For Project ID: {projectId}")); var retVal = new ProposalResult(); var project = _projectRepository.Queryable() .Include(x => x.Proposal) .Include(x => x.Stories) .Include(x => x.Contracts) .FirstAsync(x => x.Id == projectId); var org = _organizationRepository.Queryable() .Include(x => x.ProviderOrganization) .FirstOrDefaultAsync(x => x.Id == organizationId); await Task.WhenAll(project, org); if (project.Result.Proposal != null) { throw new ApplicationException("Proposal already exists"); } if (project.Result.Stories.Count == 0) { throw new ApplicationException("Project must have at least one story with one story point"); } if (project.Result.Contracts.Count == 0) { throw new ApplicationException("Project must have at least one contract"); } var proposal = new FixedPriceProposal() { Id = projectId, ObjectState = ObjectState.Added, Status = ProposalStatus.Draft, ProposalType = ProposalType.Fixed, UpdatedById = _userInfo.UserId, CreatedById = _userInfo.UserId, StoryPointBasis = input.StoryPointBasis.GetValueOrDefault( project .Result.Stories.Sum(x => x.StoryPoints.GetValueOrDefault())), AgreementText = input.AgreementText, OtherPercentBasis = input.OtherPercentBasis, BudgetBasis = input.BudgetBasis, CustomerRateBasis = input.CustomerRateBasis.GetValueOrDefault(), EstimationBasis = input.EstimationBasis .GetValueOrDefault(org.Result.ProviderOrganization.EstimationBasis), WeeklyMaxHourBasis = input.WeeklyMaxHourBasis .GetValueOrDefault(project .Result.Contracts.Sum(x => x.MaxWeeklyHours)), }; proposal.StatusTransitions.Add(new ProposalStatusTransition() { Status = ProposalStatus.Draft, ObjectState = ObjectState.Added }); proposal.InjectFrom(input); _logger.LogInformation(GetLogMessage("Proposal story Point basis : {0}"), proposal.StoryPointBasis); _logger.LogInformation(GetLogMessage("Proposal estimation basis : {0}"), proposal.EstimationBasis); _logger.LogInformation(GetLogMessage("Proposal customer rate basis : {0}"), proposal.CustomerRateBasis); _logger.LogInformation(GetLogMessage("Proposal other percent basis : {0}"), proposal.OtherPercentBasis); _logger.LogInformation(GetLogMessage("Proposal total hours : {0}"), proposal.TotalHours); _logger.LogInformation(GetLogMessage("Proposal total price quoted : {0}"), proposal.TotalPriceQuoted); var records = await Repository.InsertAsync(proposal, true); _logger.LogDebug(GetLogMessage("{0} records updated"), records); if (records > 0) { retVal.Succeeded = true; retVal.ProposalId = projectId; await Task.Run(() => { RaiseEvent(new ProposalCreatedEvent { ProposalId = projectId }); }); } return(retVal); }