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.technical.crm
21 
22 import java.nio.file.Path
23 import io.circe.Decoder
24 import org.make.api.technical.crm.BasicCrmResponse._
25 import org.make.api.technical.crm.CrmClient.{Account, Marketing, Transactional}
26 import org.make.api.technical.security.SecurityHelper
27 import org.make.core.Order
28 
29 import scala.concurrent.{ExecutionContext, Future}
30 import org.make.core.technical.Pagination
31 
32 trait CrmClient {
33 
34   def manageContactList(manageContactList: ManageManyContacts, account: Account = Marketing)(
35     implicit executionContext: ExecutionContext
36   ): Future[ManageManyContactsResponse]
37 
38   def manageContactListWithCsv(csvImport: CsvImport, account: Account = Marketing)(
39     implicit executionContext: ExecutionContext
40   ): Future[ManageContactsWithCsvResponse]
41 
42   def sendCsv(listId: String, csv: Path, account: Account = Marketing)(
43     implicit executionContext: ExecutionContext
44   ): Future[SendCsvResponse]
45 
46   def monitorCsvImport(jobId: Long, account: Account = Marketing)(
47     implicit executionContext: ExecutionContext
48   ): Future[ManageContactsWithCsvResponse]
49 
50   def sendEmail(message: SendMessages, account: Account = Transactional)(
51     implicit executionContext: ExecutionContext
52   ): Future[SendEmailResponse]
53 
54   def getUsersInformationMailFromList(
55     listId: Option[String] = None,
56     sort: Option[String] = None,
57     order: Option[Order] = None,
58     countOnly: Option[Boolean] = None,
59     limit: Pagination.Limit,
60     offset: Pagination.Offset = Pagination.Offset(0),
61     account: Account = Marketing
62   )(implicit executionContext: ExecutionContext): Future[ContactsResponse]
63 
64   def getContactsProperties(offset: Int, limit: Pagination.Limit, account: Account = Marketing)(
65     implicit executionContext: ExecutionContext
66   ): Future[GetMailjetContactProperties]
67 
68   def deleteContactByEmail(email: String, account: Account)(implicit executionContext: ExecutionContext): Future[Unit]
69 
70   def deleteContactById(contactId: String, account: Account)(implicit executionContext: ExecutionContext): Future[Unit]
71 }
72 
73 object CrmClient {
74   sealed trait Account
75 
76   case object Marketing extends Account
77   case object Transactional extends Account
78 }
79 
80 trait CrmClientComponent {
81   def crmClient: CrmClient
82 }
83 
84 final case class SendEmailResponse(messages: Seq[SentEmail])
85 
86 object SendEmailResponse {
87   implicit val decoder: Decoder[SendEmailResponse] =
88     Decoder.forProduct1("Messages")(SendEmailResponse.apply)
89 }
90 
91 final case class SendCsvResponse(csvId: Long)
92 
93 object SendCsvResponse {
94   implicit val decoder: Decoder[SendCsvResponse] =
95     Decoder.forProduct1("ID")(SendCsvResponse.apply)
96 }
97 
98 final case class SentEmail(
99   status: String,
100   errors: Option[Seq[SendMessageError]],
101   customId: String,
102   to: Seq[MessageDetails],
103   cc: Seq[MessageDetails],
104   bcc: Seq[MessageDetails]
105 ) {
106   override def toString: String =
107     s"SentEmail: (status = $status, errors = ${errors.map(_.mkString("[", ",", "]"))}, customId = $customId, to = ${to
108       .mkString("[", ",", "]")}, cc = ${cc.mkString("[", ",", "]")}, bcc = ${bcc.mkString("[", ",", "]")})"
109 }
110 
111 object SentEmail {
112   implicit val decoder: Decoder[SentEmail] =
113     Decoder.forProduct6("Status", "Errors", "CustomID", "To", "Cc", "Bcc")(SentEmail.apply)
114 }
115 
116 final case class SendMessageError(
117   errorIdentifier: String,
118   errorCode: String,
119   statusCode: Int,
120   errorMessage: String,
121   errorRelatedTo: String
122 ) {
123   override def toString: String =
124     s"SendMessageError: (errorIdentifier = $errorIdentifier, errorCode = $errorCode, " +
125       s"statusCode = $statusCode, errorMessage = $errorMessage, errorRelatedTo = $errorRelatedTo)"
126 }
127 
128 object SendMessageError {
129   implicit val decoder: Decoder[SendMessageError] =
130     Decoder.forProduct5("ErrorIdentifier", "ErrorCode", "StatusCode", "ErrorMessage", "ErrorRelatedTo")(
131       SendMessageError.apply
132     )
133 }
134 
135 final case class MessageDetails(email: String, messageUuid: String, messageId: Long, messageHref: String) {
136   override def toString: String =
137     s"MessageDetails: (email = ${SecurityHelper.anonymizeEmail(email)}, messageUuid = $messageUuid, " +
138       s"messageId = $messageId, messageHref = $messageHref)"
139 }
140 
141 object MessageDetails {
142   implicit val decoder: Decoder[MessageDetails] =
143     Decoder.forProduct4("Email", "MessageUUID", "MessageID", "MessageHref")(MessageDetails.apply)
144 }
145 
146 final case class BasicCrmResponse[T](count: Int, total: Int, data: Seq[T])
147 
148 object BasicCrmResponse {
149   def createDecoder[T](implicit tDecoder: Decoder[T]): Decoder[BasicCrmResponse[T]] =
150     Decoder.forProduct3("Count", "Total", "Data")(BasicCrmResponse.apply)
151 
152   type ContactsResponse = BasicCrmResponse[ContactDataResponse]
153   type ManageManyContactsResponse = BasicCrmResponse[JobId]
154   type GetMailjetContactProperties = BasicCrmResponse[MailjetContactProperties]
155   type ManageContactsWithCsvResponse = BasicCrmResponse[CsvImportResponse]
156 
157   implicit val contactsResponseDecoder: Decoder[ContactsResponse] = createDecoder[ContactDataResponse]
158   implicit val manageManyContactsResponseDecoder: Decoder[ManageManyContactsResponse] = createDecoder[JobId]
159   implicit val getMailjetContactPropertiesResponseDecoder: Decoder[GetMailjetContactProperties] =
160     createDecoder[MailjetContactProperties]
161   implicit val manageContactsWithCsvResponseDecoder: Decoder[ManageContactsWithCsvResponse] =
162     createDecoder[CsvImportResponse]
163 }
164 
165 final case class CsvImportResponse(jobId: Long, dataId: Long, errorCount: Int, status: String)
166 
167 object CsvImportResponse {
168   implicit val decoder: Decoder[CsvImportResponse] =
169     Decoder.forProduct4("ID", "DataID", "Errcount", "Status")(CsvImportResponse.apply)
170 }
171 
172 final case class ContactDataResponse(
173   isExcludedFromCampaigns: Boolean,
174   name: String,
175   createdAt: String,
176   deliveredCount: Int,
177   email: String,
178   exclusionFromCampaignsUpdatedAt: String,
179   id: Long,
180   isOptInPending: Boolean,
181   isSpamComplaining: Boolean,
182   lastActivityAt: String,
183   lastUpdateAt: String
184 )
185 
186 object ContactDataResponse {
187   implicit val decoder: Decoder[ContactDataResponse] =
188     Decoder.forProduct11(
189       "IsExcludedFromCampaigns",
190       "Name",
191       "CreatedAt",
192       "DeliveredCount",
193       "Email",
194       "ExclusionFromCampaignsUpdatedAt",
195       "ID",
196       "IsOptInPending",
197       "IsSpamComplaining",
198       "LastActivityAt",
199       "LastUpdateAt"
200     )(ContactDataResponse.apply)
201 }
202 
203 final case class JobId(jobId: Long)
204 
205 object JobId {
206   implicit val decoder: Decoder[JobId] =
207     Decoder.forProduct1("JobID")(JobId.apply)
208 }
209 
210 final case class MailjetContactProperties(properties: Seq[MailjetProperty], contactId: Long)
211 object MailjetContactProperties {
212   implicit val decoder: Decoder[MailjetContactProperties] =
213     Decoder.forProduct2("Data", "ContactID")(MailjetContactProperties.apply)
214 }
215 
216 final case class MailjetProperty(name: String, value: String)
217 object MailjetProperty {
218   implicit val decoder: Decoder[MailjetProperty] = Decoder.forProduct2("Name", "Value")(MailjetProperty.apply)
219 }
Line Stmt Id Pos Tree Symbol Tests Code
88 29750 3146 - 3146 Select org.make.api.technical.crm.SentEmail.decoder crm.this.SentEmail.decoder
88 29142 3135 - 3145 Literal <nosymbol> "Messages"
88 28427 3115 - 3171 ApplyToImplicitArgs io.circe.ProductDecoders.forProduct1 io.circe.Decoder.forProduct1[org.make.api.technical.crm.SendEmailResponse, Seq[org.make.api.technical.crm.SentEmail]]("Messages")(((messages: Seq[org.make.api.technical.crm.SentEmail]) => SendEmailResponse.apply(messages)))(circe.this.Decoder.decodeSeq[org.make.api.technical.crm.SentEmail](crm.this.SentEmail.decoder))
88 29351 3146 - 3146 ApplyToImplicitArgs io.circe.Decoder.decodeSeq circe.this.Decoder.decodeSeq[org.make.api.technical.crm.SentEmail](crm.this.SentEmail.decoder)
88 28298 3147 - 3170 Apply org.make.api.technical.crm.SendEmailResponse.apply SendEmailResponse.apply(messages)
95 29845 3322 - 3326 Literal <nosymbol> "ID"
95 30039 3302 - 3350 ApplyToImplicitArgs io.circe.ProductDecoders.forProduct1 io.circe.Decoder.forProduct1[org.make.api.technical.crm.SendCsvResponse, Long]("ID")(((csvId: Long) => SendCsvResponse.apply(csvId)))(circe.this.Decoder.decodeLong)
95 29006 3328 - 3349 Apply org.make.api.technical.crm.SendCsvResponse.apply SendCsvResponse.apply(csvId)
95 28611 3327 - 3327 Select io.circe.Decoder.decodeLong circe.this.Decoder.decodeLong
113 29879 3948 - 3948 Select org.make.api.technical.crm.MessageDetails.decoder crm.this.MessageDetails.decoder
113 29723 3948 - 3948 Select io.circe.Decoder.decodeString circe.this.Decoder.decodeString
113 28377 3948 - 3948 ApplyToImplicitArgs io.circe.Decoder.decodeOption circe.this.Decoder.decodeOption[Seq[org.make.api.technical.crm.SendMessageError]](circe.this.Decoder.decodeSeq[org.make.api.technical.crm.SendMessageError](crm.this.SendMessageError.decoder))
113 29325 3948 - 3948 Select org.make.api.technical.crm.MessageDetails.decoder crm.this.MessageDetails.decoder
113 28529 3936 - 3940 Literal <nosymbol> "Cc"
113 29103 3898 - 3906 Literal <nosymbol> "Status"
113 29716 3918 - 3928 Literal <nosymbol> "CustomID"
113 29357 3930 - 3934 Literal <nosymbol> "To"
113 28304 3908 - 3916 Literal <nosymbol> "Errors"
113 29874 3942 - 3947 Literal <nosymbol> "Bcc"
113 30454 3948 - 3948 Select org.make.api.technical.crm.MessageDetails.decoder crm.this.MessageDetails.decoder
113 30448 3948 - 3948 Select io.circe.Decoder.decodeString circe.this.Decoder.decodeString
113 28537 3948 - 3948 ApplyToImplicitArgs io.circe.Decoder.decodeSeq circe.this.Decoder.decodeSeq[org.make.api.technical.crm.MessageDetails](crm.this.MessageDetails.decoder)
113 30008 3948 - 3948 ApplyToImplicitArgs io.circe.Decoder.decodeSeq circe.this.Decoder.decodeSeq[org.make.api.technical.crm.MessageDetails](crm.this.MessageDetails.decoder)
113 29069 3948 - 3948 ApplyToImplicitArgs io.circe.Decoder.decodeSeq circe.this.Decoder.decodeSeq[org.make.api.technical.crm.MessageDetails](crm.this.MessageDetails.decoder)
113 30050 3948 - 3948 Select org.make.api.technical.crm.SendMessageError.decoder crm.this.SendMessageError.decoder
113 29012 3949 - 3964 Apply org.make.api.technical.crm.SentEmail.apply SentEmail.apply(status, errors, customId, to, cc, bcc)
113 29221 3948 - 3948 ApplyToImplicitArgs io.circe.Decoder.decodeSeq circe.this.Decoder.decodeSeq[org.make.api.technical.crm.SendMessageError](crm.this.SendMessageError.decoder)
113 29140 3878 - 3965 ApplyToImplicitArgs io.circe.ProductDecoders.forProduct6 io.circe.Decoder.forProduct6[org.make.api.technical.crm.SentEmail, String, Option[Seq[org.make.api.technical.crm.SendMessageError]], String, Seq[org.make.api.technical.crm.MessageDetails], Seq[org.make.api.technical.crm.MessageDetails], Seq[org.make.api.technical.crm.MessageDetails]]("Status", "Errors", "CustomID", "To", "Cc", "Bcc")(((status: String, errors: Option[Seq[org.make.api.technical.crm.SendMessageError]], customId: String, to: Seq[org.make.api.technical.crm.MessageDetails], cc: Seq[org.make.api.technical.crm.MessageDetails], bcc: Seq[org.make.api.technical.crm.MessageDetails]) => SentEmail.apply(status, errors, customId, to, cc, bcc)))(circe.this.Decoder.decodeString, circe.this.Decoder.decodeOption[Seq[org.make.api.technical.crm.SendMessageError]](circe.this.Decoder.decodeSeq[org.make.api.technical.crm.SendMessageError](crm.this.SendMessageError.decoder)), circe.this.Decoder.decodeString, circe.this.Decoder.decodeSeq[org.make.api.technical.crm.MessageDetails](crm.this.MessageDetails.decoder), circe.this.Decoder.decodeSeq[org.make.api.technical.crm.MessageDetails](crm.this.MessageDetails.decoder), circe.this.Decoder.decodeSeq[org.make.api.technical.crm.MessageDetails](crm.this.MessageDetails.decoder))
124 28379 4162 - 4345 Apply java.lang.String.+ ("SendMessageError: (errorIdentifier = ".+(SendMessageError.this.errorIdentifier).+(", errorCode = ").+(SendMessageError.this.errorCode).+(", "): String).+(("statusCode = ".+(SendMessageError.this.statusCode).+(", errorMessage = ").+(SendMessageError.this.errorMessage).+(", errorRelatedTo = ").+(SendMessageError.this.errorRelatedTo).+(")"): String))
130 29143 4530 - 4530 Select io.circe.Decoder.decodeString circe.this.Decoder.decodeString
130 30012 4530 - 4530 Select io.circe.Decoder.decodeString circe.this.Decoder.decodeString
130 29842 4497 - 4511 Literal <nosymbol> "ErrorMessage"
130 28442 4431 - 4566 ApplyToImplicitArgs io.circe.ProductDecoders.forProduct5 io.circe.Decoder.forProduct5[org.make.api.technical.crm.SendMessageError, String, String, Int, String, String]("ErrorIdentifier", "ErrorCode", "StatusCode", "ErrorMessage", "ErrorRelatedTo")(((errorIdentifier: String, errorCode: String, statusCode: Int, errorMessage: String, errorRelatedTo: String) => SendMessageError.apply(errorIdentifier, errorCode, statusCode, errorMessage, errorRelatedTo)))(circe.this.Decoder.decodeString, circe.this.Decoder.decodeString, circe.this.Decoder.decodeInt, circe.this.Decoder.decodeString, circe.this.Decoder.decodeString)
130 29707 4451 - 4468 Literal <nosymbol> "ErrorIdentifier"
130 29073 4513 - 4529 Literal <nosymbol> "ErrorRelatedTo"
130 28403 4483 - 4495 Literal <nosymbol> "StatusCode"
130 28875 4530 - 4530 Select io.circe.Decoder.decodeString circe.this.Decoder.decodeString
130 29712 4530 - 4530 Select io.circe.Decoder.decodeString circe.this.Decoder.decodeString
130 29329 4470 - 4481 Literal <nosymbol> "ErrorCode"
130 28348 4530 - 4530 Select io.circe.Decoder.decodeInt circe.this.Decoder.decodeInt
131 30391 4538 - 4560 Apply org.make.api.technical.crm.SendMessageError.apply SendMessageError.apply(errorIdentifier, errorCode, statusCode, errorMessage, errorRelatedTo)
137 29849 4716 - 4876 Apply java.lang.String.+ ("MessageDetails: (email = ".+(org.make.api.technical.security.SecurityHelper.anonymizeEmail(MessageDetails.this.email)).+(", messageUuid = ").+(MessageDetails.this.messageUuid).+(", "): String).+(("messageId = ".+(MessageDetails.this.messageId).+(", messageHref = ").+(MessageDetails.this.messageHref).+(")"): String))
143 28533 5029 - 5029 Select io.circe.Decoder.decodeLong circe.this.Decoder.decodeLong
143 29669 5029 - 5029 Select io.circe.Decoder.decodeString circe.this.Decoder.decodeString
143 28966 4978 - 4985 Literal <nosymbol> "Email"
143 29817 5029 - 5029 Select io.circe.Decoder.decodeString circe.this.Decoder.decodeString
143 29117 5015 - 5028 Literal <nosymbol> "MessageHref"
143 28878 5029 - 5029 Select io.circe.Decoder.decodeString circe.this.Decoder.decodeString
143 30397 4987 - 5000 Literal <nosymbol> "MessageUUID"
143 28354 5030 - 5050 Apply org.make.api.technical.crm.MessageDetails.apply MessageDetails.apply(email, messageUuid, messageId, messageHref)
143 29969 5002 - 5013 Literal <nosymbol> "MessageID"
143 28970 4958 - 5051 ApplyToImplicitArgs io.circe.ProductDecoders.forProduct4 io.circe.Decoder.forProduct4[org.make.api.technical.crm.MessageDetails, String, String, Long, String]("Email", "MessageUUID", "MessageID", "MessageHref")(((email: String, messageUuid: String, messageId: Long, messageHref: String) => MessageDetails.apply(email, messageUuid, messageId, messageHref)))(circe.this.Decoder.decodeString, circe.this.Decoder.decodeString, circe.this.Decoder.decodeLong, circe.this.Decoder.decodeString)
150 28488 5292 - 5292 ApplyToImplicitArgs io.circe.Decoder.decodeSeq circe.this.Decoder.decodeSeq[T](tDecoder)
150 29224 5285 - 5291 Literal <nosymbol> "Data"
150 28884 5292 - 5292 Select io.circe.Decoder.decodeInt circe.this.Decoder.decodeInt
150 30400 5267 - 5274 Literal <nosymbol> "Count"
150 29673 5292 - 5292 Select io.circe.Decoder.decodeInt circe.this.Decoder.decodeInt
150 29915 5247 - 5316 ApplyToImplicitArgs io.circe.ProductDecoders.forProduct3 io.circe.Decoder.forProduct3[org.make.api.technical.crm.BasicCrmResponse[T], Int, Int, Seq[T]]("Count", "Total", "Data")(((count: Int, total: Int, data: Seq[T]) => BasicCrmResponse.apply[T](count, total, data)))(circe.this.Decoder.decodeInt, circe.this.Decoder.decodeInt, circe.this.Decoder.decodeSeq[T](tDecoder))
150 29631 5276 - 5283 Literal <nosymbol> "Total"
150 28315 5293 - 5315 Apply org.make.api.technical.crm.BasicCrmResponse.apply BasicCrmResponse.apply[T](count, total, data)
157 28947 5679 - 5679 Select org.make.api.technical.crm.ContactDataResponse.decoder crm.this.ContactDataResponse.decoder
157 30364 5666 - 5700 ApplyToImplicitArgs org.make.api.technical.crm.BasicCrmResponse.createDecoder BasicCrmResponse.this.createDecoder[org.make.api.technical.crm.ContactDataResponse](crm.this.ContactDataResponse.decoder)
158 29636 5802 - 5802 Select org.make.api.technical.crm.JobId.decoder crm.this.JobId.decoder
158 29184 5789 - 5809 ApplyToImplicitArgs org.make.api.technical.crm.BasicCrmResponse.createDecoder BasicCrmResponse.this.createDecoder[org.make.api.technical.crm.JobId](crm.this.JobId.decoder)
160 28344 5925 - 5925 Select org.make.api.technical.crm.MailjetContactProperties.decoder crm.this.MailjetContactProperties.decoder
160 29682 5912 - 5951 ApplyToImplicitArgs org.make.api.technical.crm.BasicCrmResponse.createDecoder BasicCrmResponse.this.createDecoder[org.make.api.technical.crm.MailjetContactProperties](crm.this.MailjetContactProperties.decoder)
162 28910 6063 - 6063 Select org.make.api.technical.crm.CsvImportResponse.decoder crm.this.CsvImportResponse.decoder
162 28498 6050 - 6082 ApplyToImplicitArgs org.make.api.technical.crm.BasicCrmResponse.createDecoder BasicCrmResponse.this.createDecoder[org.make.api.technical.crm.CsvImportResponse](crm.this.CsvImportResponse.decoder)
169 29753 6323 - 6323 Select io.circe.Decoder.decodeLong circe.this.Decoder.decodeLong
169 29812 6266 - 6348 ApplyToImplicitArgs io.circe.ProductDecoders.forProduct4 io.circe.Decoder.forProduct4[org.make.api.technical.crm.CsvImportResponse, Long, Long, Int, String]("ID", "DataID", "Errcount", "Status")(((jobId: Long, dataId: Long, errorCount: Int, status: String) => CsvImportResponse.apply(jobId, dataId, errorCount, status)))(circe.this.Decoder.decodeLong, circe.this.Decoder.decodeLong, circe.this.Decoder.decodeInt, circe.this.Decoder.decodeString)
169 28305 6323 - 6323 Select io.circe.Decoder.decodeLong circe.this.Decoder.decodeLong
169 29193 6324 - 6347 Apply org.make.api.technical.crm.CsvImportResponse.apply CsvImportResponse.apply(jobId, dataId, errorCount, status)
169 30371 6302 - 6312 Literal <nosymbol> "Errcount"
169 29052 6292 - 6300 Literal <nosymbol> "DataID"
169 30287 6323 - 6323 Select io.circe.Decoder.decodeString circe.this.Decoder.decodeString
169 28917 6323 - 6323 Select io.circe.Decoder.decodeInt circe.this.Decoder.decodeInt
169 29888 6286 - 6290 Literal <nosymbol> "ID"
169 29598 6314 - 6322 Literal <nosymbol> "Status"
189 29056 6783 - 6808 Literal <nosymbol> "IsExcludedFromCampaigns"
190 30355 6816 - 6822 Literal <nosymbol> "Name"
191 29603 6830 - 6841 Literal <nosymbol> "CreatedAt"
192 29153 6849 - 6865 Literal <nosymbol> "DeliveredCount"
193 28311 6873 - 6880 Literal <nosymbol> "Email"
194 29755 6888 - 6921 Literal <nosymbol> "ExclusionFromCampaignsUpdatedAt"
195 28852 6929 - 6933 Literal <nosymbol> "ID"
196 30292 6941 - 6957 Literal <nosymbol> "IsOptInPending"
197 29819 6965 - 6984 Literal <nosymbol> "IsSpamComplaining"
198 29023 6992 - 7008 Literal <nosymbol> "LastActivityAt"
199 30360 7016 - 7030 Literal <nosymbol> "LastUpdateAt"
200 29529 7037 - 7062 Apply org.make.api.technical.crm.ContactDataResponse.apply ContactDataResponse.apply(isExcludedFromCampaigns, name, createdAt, deliveredCount, email, exclusionFromCampaignsUpdatedAt, id, isOptInPending, isSpamComplaining, lastActivityAt, lastUpdateAt)
200 29642 6755 - 7063 ApplyToImplicitArgs io.circe.ProductDecoders.forProduct11 io.circe.Decoder.forProduct11[org.make.api.technical.crm.ContactDataResponse, Boolean, String, String, Int, String, String, Long, Boolean, Boolean, String, String]("IsExcludedFromCampaigns", "Name", "CreatedAt", "DeliveredCount", "Email", "ExclusionFromCampaignsUpdatedAt", "ID", "IsOptInPending", "IsSpamComplaining", "LastActivityAt", "LastUpdateAt")(((isExcludedFromCampaigns: Boolean, name: String, createdAt: String, deliveredCount: Int, email: String, exclusionFromCampaignsUpdatedAt: String, id: Long, isOptInPending: Boolean, isSpamComplaining: Boolean, lastActivityAt: String, lastUpdateAt: String) => ContactDataResponse.apply(isExcludedFromCampaigns, name, createdAt, deliveredCount, email, exclusionFromCampaignsUpdatedAt, id, isOptInPending, isSpamComplaining, lastActivityAt, lastUpdateAt)))(circe.this.Decoder.decodeBoolean, circe.this.Decoder.decodeString, circe.this.Decoder.decodeString, circe.this.Decoder.decodeInt, circe.this.Decoder.decodeString, circe.this.Decoder.decodeString, circe.this.Decoder.decodeLong, circe.this.Decoder.decodeBoolean, circe.this.Decoder.decodeBoolean, circe.this.Decoder.decodeString, circe.this.Decoder.decodeString)
200 28808 7036 - 7036 Select io.circe.Decoder.decodeString circe.this.Decoder.decodeString
200 28281 7036 - 7036 Select io.circe.Decoder.decodeString circe.this.Decoder.decodeString
200 29639 7036 - 7036 Select io.circe.Decoder.decodeString circe.this.Decoder.decodeString
200 29531 7036 - 7036 Select io.circe.Decoder.decodeBoolean circe.this.Decoder.decodeBoolean
200 29794 7036 - 7036 Select io.circe.Decoder.decodeString circe.this.Decoder.decodeString
200 29106 7036 - 7036 Select io.circe.Decoder.decodeBoolean circe.this.Decoder.decodeBoolean
200 28855 7036 - 7036 Select io.circe.Decoder.decodeInt circe.this.Decoder.decodeInt
200 30323 7036 - 7036 Select io.circe.Decoder.decodeBoolean circe.this.Decoder.decodeBoolean
200 30203 7036 - 7036 Select io.circe.Decoder.decodeString circe.this.Decoder.decodeString
200 28319 7036 - 7036 Select io.circe.Decoder.decodeString circe.this.Decoder.decodeString
200 29027 7036 - 7036 Select io.circe.Decoder.decodeLong circe.this.Decoder.decodeLong
207 28816 7184 - 7191 Literal <nosymbol> "JobID"
207 30284 7193 - 7204 Apply org.make.api.technical.crm.JobId.apply JobId.apply(jobId)
207 28986 7164 - 7205 ApplyToImplicitArgs io.circe.ProductDecoders.forProduct1 io.circe.Decoder.forProduct1[org.make.api.technical.crm.JobId, Long]("JobID")(((jobId: Long) => JobId.apply(jobId)))(circe.this.Decoder.decodeLong)
207 29891 7192 - 7192 Select io.circe.Decoder.decodeLong circe.this.Decoder.decodeLong
213 29765 7440 - 7440 ApplyToImplicitArgs io.circe.Decoder.decodeSeq circe.this.Decoder.decodeSeq[org.make.api.technical.crm.MailjetProperty](crm.this.MailjetProperty.decoder)
213 28823 7440 - 7440 Select io.circe.Decoder.decodeLong circe.this.Decoder.decodeLong
213 28386 7440 - 7440 Select org.make.api.technical.crm.MailjetProperty.decoder crm.this.MailjetProperty.decoder
213 30291 7400 - 7472 ApplyToImplicitArgs io.circe.ProductDecoders.forProduct2 io.circe.Decoder.forProduct2[org.make.api.technical.crm.MailjetContactProperties, Seq[org.make.api.technical.crm.MailjetProperty], Long]("Data", "ContactID")(((properties: Seq[org.make.api.technical.crm.MailjetProperty], contactId: Long) => MailjetContactProperties.apply(properties, contactId)))(circe.this.Decoder.decodeSeq[org.make.api.technical.crm.MailjetProperty](crm.this.MailjetProperty.decoder), circe.this.Decoder.decodeLong)
213 29507 7428 - 7439 Literal <nosymbol> "ContactID"
213 30326 7420 - 7426 Literal <nosymbol> "Data"
213 28786 7441 - 7471 Apply org.make.api.technical.crm.MailjetContactProperties.apply MailjetContactProperties.apply(properties, contactId)
218 29484 7634 - 7640 Literal <nosymbol> "Name"
218 28359 7614 - 7673 ApplyToImplicitArgs io.circe.ProductDecoders.forProduct2 io.circe.Decoder.forProduct2[org.make.api.technical.crm.MailjetProperty, String, String]("Name", "Value")(((name: String, value: String) => MailjetProperty.apply(name, value)))(circe.this.Decoder.decodeString, circe.this.Decoder.decodeString)
218 28790 7650 - 7650 Select io.circe.Decoder.decodeString circe.this.Decoder.decodeString
218 29017 7642 - 7649 Literal <nosymbol> "Value"
218 29569 7650 - 7650 Select io.circe.Decoder.decodeString circe.this.Decoder.decodeString
218 30433 7651 - 7672 Apply org.make.api.technical.crm.MailjetProperty.apply MailjetProperty.apply(name, value)