1 /*
2  *  Make.org Core API
3  *  Copyright (C) 2018 Make.org
4  *
5  * This program is free software: you can redistribute it and/or modify
6  *  it under the terms of the GNU Affero General Public License as
7  *  published by the Free Software Foundation, either version 3 of the
8  *  License, or (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU Affero General Public License for more details.
14  *
15  *  You should have received a copy of the GNU Affero General Public License
16  *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
17  *
18  */
19 
20 package org.make.api.proposal
21 
22 import java.time.ZonedDateTime
23 import akka.actor.typed.ActorRef
24 import org.make.api.proposal.ProposalActorResponse.{Envelope, VotesActorResponse}
25 import org.make.api.proposal.ProposalActorResponse.Error._
26 import org.make.api.technical.{ActorCommand, ActorProtocol}
27 import org.make.core.RequestContext
28 import org.make.core.history.HistoryActions.{VoteAndQualifications, VoteTrust}
29 import org.make.core.proposal._
30 import org.make.core.question.Question
31 import org.make.core.reference.Language
32 import org.make.core.tag.TagId
33 import org.make.core.technical.Multilingual
34 import org.make.core.user.{User, UserId}
35 
36 sealed trait ProposalActorProtocol extends ActorProtocol
37 
38 sealed trait ProposalCommand extends ActorCommand[ProposalId] with ProposalActorProtocol {
39   def id: ProposalId = proposalId
40   def proposalId: ProposalId
41   def requestContext: RequestContext
42 }
43 
44 final case class ProposeCommand(
45   proposalId: ProposalId,
46   requestContext: RequestContext,
47   user: User,
48   createdAt: ZonedDateTime,
49   content: String,
50   submittedAsLanguage: Language,
51   isAnonymous: Boolean,
52   question: Question,
53   initialProposal: Boolean,
54   proposalType: ProposalType,
55   replyTo: ActorRef[Envelope[ProposalId]]
56 ) extends ProposalCommand
57 
58 final case class UpdateProposalCommand(
59   moderator: UserId,
60   proposalId: ProposalId,
61   requestContext: RequestContext,
62   updatedAt: ZonedDateTime,
63   newContent: Option[String],
64   newTranslations: Option[Multilingual[String]],
65   tags: Seq[TagId],
66   question: Question,
67   replyTo: ActorRef[ProposalActorResponse[ModificationError, Proposal]]
68 ) extends ProposalCommand
69 
70 final case class UpdateProposalVotesCommand(
71   moderator: UserId,
72   proposalId: ProposalId,
73   requestContext: RequestContext,
74   updatedAt: ZonedDateTime,
75   votes: Seq[UpdateVoteRequest],
76   replyTo: ActorRef[ProposalActorResponse[ModificationError, Proposal]]
77 ) extends ProposalCommand
78 
79 final case class ViewProposalCommand(
80   proposalId: ProposalId,
81   requestContext: RequestContext,
82   replyTo: ActorRef[ProposalActorResponse[ProposalNotFound, Proposal]]
83 ) extends ProposalCommand
84 
85 final case class GetProposal(
86   proposalId: ProposalId,
87   requestContext: RequestContext,
88   replyTo: ActorRef[ProposalActorResponse[ProposalNotFound, Proposal]]
89 ) extends ProposalCommand
90 
91 final case class Stop(proposalId: ProposalId, requestContext: RequestContext, replyTo: ActorRef[Envelope[Unit]])
92     extends ProposalCommand
93 
94 final case class AcceptProposalCommand(
95   moderator: UserId,
96   proposalId: ProposalId,
97   requestContext: RequestContext,
98   sendNotificationEmail: Boolean,
99   newContent: Option[String],
100   newTranslations: Option[Multilingual[String]],
101   question: Question,
102   tags: Seq[TagId],
103   replyTo: ActorRef[ProposalActorResponse[ModificationError, Proposal]]
104 ) extends ProposalCommand
105 
106 final case class RefuseProposalCommand(
107   moderator: UserId,
108   proposalId: ProposalId,
109   requestContext: RequestContext,
110   sendNotificationEmail: Boolean,
111   refusalReason: Option[String],
112   replyTo: ActorRef[ProposalActorResponse[ModificationError, Proposal]]
113 ) extends ProposalCommand
114 
115 final case class PostponeProposalCommand(
116   moderator: UserId,
117   proposalId: ProposalId,
118   requestContext: RequestContext,
119   replyTo: ActorRef[ProposalActorResponse[ModificationError, Proposal]]
120 ) extends ProposalCommand
121 
122 final case class VoteProposalCommand(
123   proposalId: ProposalId,
124   maybeUserId: Option[UserId],
125   requestContext: RequestContext,
126   voteKey: VoteKey,
127   maybeOrganisationId: Option[UserId],
128   vote: Option[VoteAndQualifications],
129   voteTrust: VoteTrust,
130   newProposalsVoteThreshold: Int,
131   replyTo: ActorRef[ProposalActorResponse[VoteError, VotesActorResponse]]
132 ) extends ProposalCommand
133 
134 final case class UnvoteProposalCommand(
135   proposalId: ProposalId,
136   maybeUserId: Option[UserId],
137   requestContext: RequestContext,
138   voteKey: VoteKey,
139   maybeOrganisationId: Option[UserId],
140   vote: Option[VoteAndQualifications],
141   voteTrust: VoteTrust,
142   newProposalsVoteThreshold: Int,
143   replyTo: ActorRef[ProposalActorResponse[VoteError, VotesActorResponse]]
144 ) extends ProposalCommand
145 
146 final case class QualifyVoteCommand(
147   proposalId: ProposalId,
148   maybeUserId: Option[UserId],
149   requestContext: RequestContext,
150   voteKey: VoteKey,
151   qualificationKey: QualificationKey,
152   vote: Option[VoteAndQualifications],
153   voteTrust: VoteTrust,
154   replyTo: ActorRef[ProposalActorResponse[QualificationError, Qualification]]
155 ) extends ProposalCommand
156 
157 final case class UnqualifyVoteCommand(
158   proposalId: ProposalId,
159   maybeUserId: Option[UserId],
160   requestContext: RequestContext,
161   voteKey: VoteKey,
162   qualificationKey: QualificationKey,
163   vote: Option[VoteAndQualifications],
164   voteTrust: VoteTrust,
165   replyTo: ActorRef[ProposalActorResponse[QualificationError, Qualification]]
166 ) extends ProposalCommand
167 
168 final case class LockProposalCommand(
169   proposalId: ProposalId,
170   moderatorId: UserId,
171   moderatorName: Option[String],
172   requestContext: RequestContext,
173   replyTo: ActorRef[ProposalActorResponse[LockError, UserId]]
174 ) extends ProposalCommand
175 
176 final case class PatchProposalCommand(
177   proposalId: ProposalId,
178   userId: UserId,
179   changes: PatchProposalRequest,
180   requestContext: RequestContext,
181   replyTo: ActorRef[ProposalActorResponse[ProposalNotFound, Proposal]]
182 ) extends ProposalCommand
183 
184 final case class SetKeywordsCommand(
185   proposalId: ProposalId,
186   keywords: Seq[ProposalKeyword],
187   requestContext: RequestContext,
188   replyTo: ActorRef[ProposalActorResponse[ProposalNotFound, Proposal]]
189 ) extends ProposalCommand
190 
191 // Responses
192 
193 sealed trait ProposalActorResponse[+E, +T] extends ProposalActorProtocol {
194   def flatMap[F >: E, U](f: T => ProposalActorResponse[F, U]): ProposalActorResponse[F, U]
195 }
196 
197 object ProposalActorResponse {
198 
199   final case class Envelope[T](value: T) extends ProposalActorResponse[Nothing, T] {
200     override def flatMap[E, U](f: T => ProposalActorResponse[E, U]): ProposalActorResponse[E, U] = f(value)
201   }
202 
203   final case class VotesActorResponse(agree: VoteActorResponse, disagree: VoteActorResponse, neutral: VoteActorResponse)
204 
205   final case class VoteActorResponse(key: VoteKey, count: Int, score: Double, qualifications: Seq[Qualification])
206   case object VoteActorResponse {
207     def apply(wrapper: VotingOptionWrapper, score: Double): VoteActorResponse =
208       VoteActorResponse(
209         key = wrapper.vote.key,
210         count = wrapper.vote.count,
211         score = score,
212         qualifications = wrapper.deprecatedQualificationsSeq
213       )
214   }
215 
216   sealed trait Error[E <: Error[E]] extends ProposalActorResponse[E, Nothing] { self: E =>
217     override def flatMap[F >: E, U](f: Nothing => ProposalActorResponse[F, U]): ProposalActorResponse[E, Nothing] = self
218   }
219 
220   object Error {
221 
222     sealed trait LockError
223     sealed trait ModificationError
224     sealed trait VoteError extends QualificationError
225     sealed trait QualificationError
226 
227     sealed trait ProposalNotFound extends Error[ProposalNotFound] with LockError with ModificationError with VoteError
228     case object ProposalNotFound extends ProposalNotFound
229 
230     sealed trait VoteNotFound extends Error[VoteNotFound] with VoteError
231     case object VoteNotFound extends VoteNotFound
232 
233     sealed trait QualificationNotFound extends Error[QualificationNotFound] with QualificationError
234     case object QualificationNotFound extends QualificationNotFound
235 
236     final case class AlreadyLockedBy(moderatorName: String) extends Error[AlreadyLockedBy] with LockError
237 
238     final case class InvalidStateError(message: String) extends Error[InvalidStateError] with ModificationError
239 
240     final case class HistoryError(error: Throwable) extends Error[HistoryError] with VoteError
241 
242   }
243 }
Line Stmt Id Pos Tree Symbol Tests Code
39 14241 1556 - 1566 Select org.make.api.proposal.ProposalCommand.proposalId ProposalCommand.this.proposalId
200 17835 6664 - 6672 Apply scala.Function1.apply f.apply(Envelope.this.value)
200 12005 6666 - 6671 Select org.make.api.proposal.ProposalActorResponse.Envelope.value Envelope.this.value
208 14885 7034 - 7212 Apply org.make.api.proposal.ProposalActorResponse.VoteActorResponse.apply ProposalActorResponse.this.VoteActorResponse.apply(wrapper.vote.key, wrapper.vote.count, score, wrapper.deprecatedQualificationsSeq)
209 14392 7067 - 7083 Select org.make.core.proposal.Vote.key wrapper.vote.key
210 11113 7101 - 7119 Select org.make.core.proposal.Vote.count wrapper.vote.count
212 9362 7169 - 7204 Select org.make.core.proposal.VotingOptionWrapper.deprecatedQualificationsSeq wrapper.deprecatedQualificationsSeq