1 /* 2 * Make.org Core API 3 * Copyright (C) 2021 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.demographics 21 22 import org.make.api.extensions.MakeDBExecutionContextComponent 23 import org.make.api.technical.DatabaseTransactions._ 24 import org.make.api.technical.PersistentServiceUtils._ 25 import org.make.api.technical.ScalikeSupport._ 26 import org.make.api.technical.{PersistentCompanion, ShortenedNames} 27 import org.make.core.Order 28 import org.make.core.demographics.{DemographicsCard, DemographicsCardId, LabelsValue} 29 import org.make.core.question.QuestionId 30 import org.make.core.reference.Language 31 import org.make.core.technical.Pagination 32 33 import cats.data.NonEmptyList 34 import cats.implicits._ 35 import scalikejdbc._ 36 37 import scala.concurrent.Future 38 39 trait DefaultPersistentDemographicsCardServiceComponent extends PersistentDemographicsCardServiceComponent { 40 self: MakeDBExecutionContextComponent => 41 42 implicit val labelsBinder: Binders[NonEmptyList[LabelsValue]] = jsonNelBinder[LabelsValue] 43 44 val CountColumnName = "count" 45 46 override lazy val persistentDemographicsCardService: PersistentDemographicsCardService = 47 new PersistentDemographicsCardService with ShortenedNames { 48 49 private val demographicsCards = SQLSyntaxSupportFactory[DemographicsCard]() 50 private val dc = demographicsCards.syntax 51 52 private implicit val companion: PersistentCompanion[DemographicsCard, DemographicsCard] = 53 new PersistentCompanion[DemographicsCard, DemographicsCard] { 54 override val alias: SyntaxProvider[DemographicsCard] = dc 55 override val defaultSortColumns: NonEmptyList[SQLSyntax] = NonEmptyList.of(alias.name) 56 override val columnNames: Seq[String] = 57 Seq("name", "question_id", "layout", "dataType", "languages", "titles", "createdAt", "updatedAt") 58 } 59 60 override def get(id: DemographicsCardId): Future[Option[DemographicsCard]] = { 61 implicit val context: EC = readExecutionContext 62 Future(NamedDB("READ").retryableTx { implicit session => 63 withSQL { 64 select.from(demographicsCards.as(dc)).where.eq(dc.id, id) 65 }.map(demographicsCards.apply(dc.resultName)) 66 .single() 67 }) 68 } 69 70 override def list( 71 offset: Option[Pagination.Offset], 72 end: Option[Pagination.End], 73 sort: Option[String], 74 order: Option[Order], 75 languages: Option[List[Language]], 76 dataType: Option[String], 77 questionId: Option[QuestionId] 78 ): Future[Seq[DemographicsCard]] = { 79 implicit val context: EC = readExecutionContext 80 Future(NamedDB("READ").retryableTx { implicit session => 81 withSQL { 82 sortOrderQuery( 83 offset.orZero, 84 end, 85 sort, 86 order, 87 select 88 .from(demographicsCards.as(dc)) 89 .where( 90 sqls.toAndConditionOpt( 91 languages.map(l => sqls"${dc.languages} @> ARRAY[${l.map(_.value)}]"), 92 dataType.map(sqls.like(dc.dataType, _)), 93 questionId.map(sqls.eq(dc.questionId, _)) 94 ) 95 ) 96 ) 97 }.map(demographicsCards.apply(dc.resultName)) 98 .list() 99 }) 100 } 101 102 override def persist(demographicsCard: DemographicsCard): Future[DemographicsCard] = { 103 implicit val context: EC = writeExecutionContext 104 Future(NamedDB("WRITE").retryableTx { implicit session => 105 withSQL { 106 insert.into(demographicsCards).namedValues(autoNamedValues(demographicsCard, demographicsCards.column)) 107 }.update() 108 }).as(demographicsCard) 109 } 110 111 override def modify(demographicsCard: DemographicsCard): Future[DemographicsCard] = { 112 implicit val context: EC = writeExecutionContext 113 Future(NamedDB("WRITE").retryableTx { implicit session => 114 withSQL { 115 update(demographicsCards) 116 .set(autoNamedValues(demographicsCard, demographicsCards.column, "id", "createdAt")) 117 .where 118 .eq(dc.id, demographicsCard.id) 119 }.update() 120 }).as(demographicsCard) 121 } 122 123 override def count( 124 languages: Option[List[Language]], 125 dataType: Option[String], 126 questionId: Option[QuestionId] 127 ): Future[Int] = { 128 implicit val context: EC = readExecutionContext 129 Future(NamedDB("READ").retryableTx { implicit session => 130 withSQL { 131 select(sqls.count) 132 .from(demographicsCards.as(dc)) 133 .where( 134 sqls.toAndConditionOpt( 135 languages.map(l => sqls"${dc.languages} @> ARRAY[${l.map(_.value).mkString(",")}]"), 136 dataType.map(sqls.like(dc.dataType, _)), 137 questionId.map(sqls.eq(dc.questionId, _)) 138 ) 139 ) 140 }.map(_.int(CountColumnName)).single().getOrElse(0) 141 }) 142 } 143 144 override def delete(id: DemographicsCardId): Future[Unit] = { 145 implicit val context: EC = writeExecutionContext 146 Future(NamedDB("WRITE").retryableTx { implicit session => 147 withSQL { 148 deleteFrom(demographicsCards.as(dc)).where.eq(dc.id, id) 149 }.execute() 150 }).void 151 } 152 153 } 154 }
| Line | Stmt Id | Pos | Tree | Symbol | Tests | Code |
|---|---|---|---|---|---|---|
| 42 | 20829 | 1630 - 1656 | ApplyToImplicitArgs | org.make.api.technical.ScalikeSupport.jsonNelBinder | org.make.api.technical.ScalikeSupport.jsonNelBinder[org.make.core.demographics.LabelsValue](demographics.this.LabelsValue.codec, demographics.this.LabelsValue.codec) | |
| 42 | 19622 | 1643 - 1643 | Select | org.make.core.demographics.LabelsValue.codec | demographics.this.LabelsValue.codec | |
| 42 | 21727 | 1643 - 1643 | Select | org.make.core.demographics.LabelsValue.codec | demographics.this.LabelsValue.codec | |
| 44 | 19829 | 1682 - 1689 | Literal | <nosymbol> | "count" |