Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[TRELLO-2149] Implement create website manually endpoint #1534

Merged
merged 2 commits into from
Jan 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions app/controllers/WebsiteController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import play.api.mvc.AnyContent
import play.api.mvc.ControllerComponents
import repositories.company.CompanyRepositoryInterface
import authentication.actions.UserAction.WithRole
import utils.URL

import java.time.OffsetDateTime
import scala.concurrent.ExecutionContext
Expand All @@ -36,6 +37,18 @@ class WebsiteController(
implicit val timeout: akka.util.Timeout = 5.seconds
val logger: Logger = Logger(this.getClass)

def create() = SecuredAction.andThen(WithRole(UserRole.Admin)).async(parse.json) { request =>
request.body
.validate[WebsiteCreation]
.fold(
errors => Future.successful(BadRequest(JsError.toJson(errors))),
websiteCreation =>
websitesOrchestrator
.create(URL(websiteCreation.host), websiteCreation.company.toCompany())
.map(website => Ok(Json.toJson(website)))
)
}

def fetchWithCompanies(
maybeHost: Option[String],
maybeIdentificationStatus: Option[Seq[IdentificationStatus]],
Expand Down
5 changes: 5 additions & 0 deletions app/controllers/error/AppError.scala
Original file line number Diff line number Diff line change
Expand Up @@ -507,4 +507,9 @@ object AppError {
override val titleForLogs: String = "different_user_from_request"
}

final case class CreateWebsiteError(override val details: String) extends BadRequestError {
override val `type`: String = "SC-0054"
override val title: String = "Can't create website"
override val titleForLogs: String = "cant_create_website"
}
}
10 changes: 10 additions & 0 deletions app/models/website/WebsiteCreation.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package models.website

import models.company.CompanyCreation
import play.api.libs.json.Json
import play.api.libs.json.Reads

case class WebsiteCreation(host: String, company: CompanyCreation)
object WebsiteCreation {
implicit val reads: Reads[WebsiteCreation] = Json.reads[WebsiteCreation]
}
55 changes: 48 additions & 7 deletions app/orchestrators/WebsitesOrchestrator.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package orchestrators
import cats.implicits.catsSyntaxMonadError
import cats.implicits.catsSyntaxOption
import controllers.error.AppError.CannotDeleteWebsite
import controllers.error.AppError.CreateWebsiteError
import controllers.error.AppError.MalformedHost
import controllers.error.AppError.WebsiteHostIsAlreadyIdentified
import controllers.error.AppError.WebsiteNotFound
Expand Down Expand Up @@ -42,6 +43,26 @@ class WebsitesOrchestrator(

val logger: Logger = Logger(this.getClass)

def create(url: URL, company: Company): Future[Website] =
for {
host <- url.getHost.liftTo[Future](MalformedHost(url.value))
createdCompany <- companyRepository.getOrCreate(company.siret, company)
identified <- repository.listIdentified(host)
notAssociatedToCompany <- repository.listNotAssociatedToCompany(host)
_ <-
if (notAssociatedToCompany.nonEmpty || identified.flatMap(_.companyId).contains(createdCompany.id))
Future.failed(CreateWebsiteError("Impossible de créer un site web s'il est déjà associé mais pas identifié"))
else
Future.unit
website = Website(
host = host,
companyCountry = None,
companyId = Some(createdCompany.id),
identificationStatus = IdentificationStatus.Identified
)
createdWebsite <- repository.create(website)
} yield createdWebsite

def searchByHost(host: String): Future[Seq[Country]] =
for {
validHost <- URL(host).getHost.liftTo[Future](MalformedHost(host))
Expand Down Expand Up @@ -82,7 +103,14 @@ class WebsitesOrchestrator(
newIdentificationStatus: IdentificationStatus,
user: User
): Future[Website] = for {
website <- findWebsite(websiteId)
website <- findWebsite(websiteId)
identified <- repository.listIdentified(website.host)
_ <-
if (identified.length > 1)
Future.failed(
CreateWebsiteError("Le status ne peut pas être modifié si plus d'un siret est associé au site web")
)
else Future.unit
_ = if (website.companyCountry.isEmpty && website.companyId.isEmpty) {
throw WebsiteNotIdentified(website.host)
}
Expand All @@ -102,7 +130,7 @@ class WebsitesOrchestrator(
_ = logger.debug(s"Company Siret is ${maybeCompany.map(_.siret)}")
_ <- maybeCompany
.map(company => updatePreviousReportsAssociatedToWebsite(website.host, company, user.id))
.getOrElse(Future.successful(()))
.getOrElse(Future.unit)
} yield ()
} else Future.unit
} yield updatedWebsite
Expand All @@ -122,9 +150,16 @@ class WebsitesOrchestrator(
for {
company <- {
logger.debug(s"Updating website (id ${websiteId}) with company siret : ${companyToAssign.siret}")
getOrCreateCompay(companyToAssign)
getOrCreateCompany(companyToAssign)
}
website <- findWebsite(websiteId)
website <- findWebsite(websiteId)
identified <- repository.listIdentified(website.host)
_ <-
if (identified.length > 1 && identified.flatMap(_.companyId).contains(company.id)) {
Future.failed(
CreateWebsiteError("L'entreprise ne peut pas être modifiée si plus d'un siret est associé au site web")
)
} else Future.unit
websiteToUpdate = website.copy(
companyCountry = None,
companyId = Some(company.id)
Expand All @@ -135,9 +170,14 @@ class WebsitesOrchestrator(

def updateCompanyCountry(websiteId: WebsiteId, companyCountry: String, user: User): Future[WebsiteAndCompany] = for {
website <- {
logger.debug(s"Updating website (id ${websiteId.value}) with company country : ${companyCountry}")
logger.debug(s"Updating website (id ${websiteId.value}) with company country : $companyCountry")
findWebsite(websiteId)
}
identified <- repository.listIdentified(website.host)
_ <-
if (identified.length > 1)
Future.failed(CreateWebsiteError("Le pays ne peut pas être modifié si plus d'un siret est associé au site web"))
else Future.unit
websiteToUpdate = website.copy(
companyCountry = Some(companyCountry),
companyId = None
Expand All @@ -162,10 +202,11 @@ class WebsitesOrchestrator(
for {
maybeWebsite <- repository.get(websiteId)
website <- maybeWebsite.liftTo[Future](WebsiteNotFound(websiteId))
identified <- repository.listIdentified(website.host)
isWebsiteUnderInvestigation = website.investigationStatus != NotProcessed
isWebsiteIdentified = website.identificationStatus == Identified
_ <-
if (isWebsiteIdentified || isWebsiteUnderInvestigation) {
if (identified.length < 2 && (isWebsiteIdentified || isWebsiteUnderInvestigation)) {
logger.debug(s"Cannot delete identified / under investigation website")
Future.failed(CannotDeleteWebsite(website.host))
} else {
Expand All @@ -184,7 +225,7 @@ class WebsitesOrchestrator(

def listInvestigationStatus(): Seq[InvestigationStatus] = InvestigationStatus.values

private[this] def getOrCreateCompay(companyCreate: CompanyCreation): Future[Company] = companyRepository
private[this] def getOrCreateCompany(companyCreate: CompanyCreation): Future[Company] = companyRepository
.getOrCreate(
companyCreate.siret,
companyCreate.toCompany()
Expand Down
19 changes: 19 additions & 0 deletions app/repositories/website/WebsiteRepository.scala
Original file line number Diff line number Diff line change
Expand Up @@ -202,4 +202,23 @@ class WebsiteRepository(
.result
)

def listNotAssociatedToCompany(host: String): Future[Seq[Website]] =
db.run(
table
.filter(_.host === host)
.filter(website =>
website.companyCountry.isDefined || (website.identificationStatus inSet List(
IdentificationStatus.NotIdentified
))
)
.result
)

def listIdentified(host: String): Future[Seq[Website]] =
db.run(
table
.filter(_.host === host)
.filter(_.identificationStatus inSet List(IdentificationStatus.Identified))
.result
)
}
4 changes: 4 additions & 0 deletions app/repositories/website/WebsiteRepositoryInterface.scala
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,8 @@ trait WebsiteRepositoryInterface extends TypedCRUDRepositoryInterface[Website, W
start: Option[LocalDate] = None,
end: Option[LocalDate] = None
): Future[List[(String, Int)]]

def listNotAssociatedToCompany(host: String): Future[Seq[Website]]

def listIdentified(host: String): Future[Seq[Website]]
}
1 change: 1 addition & 0 deletions conf/routes
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ GET /api/resources/investigation-status controll
POST /api/website-investigations controllers.WebsiteController.updateInvestigation()
# Websites API
GET /api/websites controllers.WebsiteController.fetchWithCompanies(host: Option[String], identificationStatus: Option[Seq[IdentificationStatus]], offset: Option[Long], limit: Option[Int],investigationStatus: Option[Seq[InvestigationStatus]],start: Option[OffsetDateTime],end: Option[OffsetDateTime],hasAssociation: Option[Boolean],isOpen: Option[Boolean])
POST /api/websites controllers.WebsiteController.create()
GET /api/websites/search-url controllers.WebsiteController.searchByHost(url: String)
GET /api/websites/unregistered controllers.WebsiteController.fetchUnregisteredHost(q: Option[String], start: Option[String], end: Option[String])
GET /api/websites/unregistered/extract controllers.WebsiteController.extractUnregisteredHost(q: Option[String], start: Option[String], end: Option[String])
Expand Down
Loading