diff --git a/src/back/routes/proposal.ts b/src/back/routes/proposal.ts index 1b75946b3..448d88193 100644 --- a/src/back/routes/proposal.ts +++ b/src/back/routes/proposal.ts @@ -560,7 +560,10 @@ export async function updateProposalStatus(req: WithAuth({ + id, + }) + updatedProposal && DiscourseService.commentUpdatedProposal(updatedProposal) return { ...proposal, diff --git a/src/entities/Proposal/jobs.test.ts b/src/entities/Proposal/jobs.test.ts index 3aafe142d..56e31701e 100644 --- a/src/entities/Proposal/jobs.test.ts +++ b/src/entities/Proposal/jobs.test.ts @@ -40,7 +40,7 @@ describe('finishProposals', () => { beforeAll(() => { jest.spyOn(ProposalModel, 'getFinishProposalQuery') jest.spyOn(CoauthorModel, 'findAllByProposals').mockResolvedValue([]) - jest.spyOn(DiscourseService, 'commentProposalUpdateInDiscourse').mockImplementation(() => {}) + jest.spyOn(DiscourseService, 'commentUpdatedProposal').mockImplementation(() => {}) jest.spyOn(DiscordService, 'init').mockImplementation(() => {}) jest.spyOn(DiscordService, 'finishProposal').mockImplementation(() => {}) jest.spyOn(DiscordService, 'newProposal').mockImplementation(() => {}) diff --git a/src/entities/Proposal/jobs.ts b/src/entities/Proposal/jobs.ts index c50a10df7..97ad1e2a1 100644 --- a/src/entities/Proposal/jobs.ts +++ b/src/entities/Proposal/jobs.ts @@ -56,15 +56,15 @@ function updateCategoryBudget(proposal: ProposalAttributes, budgetForProposal: B } async function getProposalsVotingResult(proposals: ProposalAttributes[]) { - const pendingProposalsVotingResult: ProposalVotingResult[] = [] + const proposalsWithVotingResult: ProposalVotingResult[] = [] for (const proposal of proposals) { const outcome = await calculateVotingResult(proposal) if (!outcome) { continue } - pendingProposalsVotingResult.push({ ...proposal, ...outcome }) + proposalsWithVotingResult.push({ ...proposal, ...outcome }) } - return pendingProposalsVotingResult + return proposalsWithVotingResult } export async function getFinishableLinkedProposals( diff --git a/src/entities/Proposal/model.ts b/src/entities/Proposal/model.ts index 059686126..9edb8d179 100644 --- a/src/entities/Proposal/model.ts +++ b/src/entities/Proposal/model.ts @@ -130,6 +130,19 @@ export default class ProposalModel extends Model { return results.map((item) => ProposalModel.parse(item)) } + static async findByIds(ids: string[]): Promise { + const query = SQL` + SELECT * + FROM ${table(ProposalModel)} + WHERE "id" IN (${join( + ids.map((id) => SQL`${id}`), + SQL`, ` + )})` + + const results = await this.namedQuery('find_by_ids', query) + return results.map((item) => ProposalModel.parse(item)) + } + static async getSitemapProposals(page: number): Promise<{ id: string }[]> { const query = SQL` SELECT id diff --git a/src/services/DiscourseService.ts b/src/services/DiscourseService.ts index 6b0069e46..6d1e983ac 100644 --- a/src/services/DiscourseService.ts +++ b/src/services/DiscourseService.ts @@ -8,7 +8,7 @@ import ProposalModel from '../entities/Proposal/model' import { ProposalWithOutcome } from '../entities/Proposal/outcome' import * as proposalTemplates from '../entities/Proposal/templates' import { getUpdateMessage } from '../entities/Proposal/templates/messages' -import { ProposalAttributes, ProposalStatus } from '../entities/Proposal/types' +import { ProposalAttributes } from '../entities/Proposal/types' import { forumUrl, proposalUrl } from '../entities/Proposal/utils' import * as updateTemplates from '../entities/Updates/templates' import { UpdateAttributes } from '../entities/Updates/types' @@ -154,18 +154,10 @@ export class DiscourseService { } } - // TODO: change getUpdateMessage to receive update values instead of having to fetch updated proposal - // TODO: votes are not necessary in all cases, they could be fetched only when needed - static commentProposalUpdateInDiscourse(id: string) { + static commentUpdatedProposal(updatedProposal: ProposalAttributes) { inBackground(async () => { - const updatedProposal: ProposalAttributes | undefined = await ProposalModel.findOne({ - id, - }) - if (!updatedProposal) { - logger.error('Invalid proposal id for discourse update', { id }) - return - } - const votes = await VoteService.getVotes(id) + // TODO: votes are not necessary in all cases, they could be fetched only when needed + const votes = await VoteService.getVotes(updatedProposal.id) const updateMessage = getUpdateMessage(updatedProposal, votes) const discourseComment: DiscourseComment = { topic_id: updatedProposal.discourse_topic_id, @@ -177,11 +169,12 @@ export class DiscourseService { } static commentFinishedProposals(proposalsWithOutcome: ProposalWithOutcome[]) { - proposalsWithOutcome.forEach((proposal) => { - //TODO: is it ok that we only notify finished proposals? (what about passed/rejected/OOB?) - if (proposal.newStatus === ProposalStatus.Finished) { - this.commentProposalUpdateInDiscourse(proposal.id) - } + inBackground(async () => { + const ids = proposalsWithOutcome.map(({ id }) => id) + const updatedProposals = await ProposalModel.findByIds(ids) + updatedProposals.forEach((proposal) => { + this.commentUpdatedProposal(proposal) + }) }) } }