diff --git a/modules/service/src/main/scala/lucuma/odb/service/ConfigurationService.scala b/modules/service/src/main/scala/lucuma/odb/service/ConfigurationService.scala index a022f7b32..4b04f04a4 100644 --- a/modules/service/src/main/scala/lucuma/odb/service/ConfigurationService.scala +++ b/modules/service/src/main/scala/lucuma/odb/service/ConfigurationService.scala @@ -52,7 +52,7 @@ trait ConfigurationService[F[_]] { /** Inserts (or selects) a `ConfigurationRequest` based on the configuration of `oid`. */ def canonicalizeRequest(input: CreateConfigurationRequestInput)(using Transaction[F]): F[Result[ConfigurationRequest]] - /** Creates`ConfigurationRequest`s as needed to ensure that one exists for each observation in `pid`. */ + /** Creates`ConfigurationRequest`s as needed to ensure that one exists for each non-inactive, non-calibration observation in `pid`. */ def canonicalizeAll(pid: Program.Id)(using Transaction[F]): F[Result[Map[Observation.Id, ConfigurationRequest]]] /** Deletes all `ConfigurationRequest`s for `pid`, returning the ids of deleted configurations. */ @@ -150,9 +150,6 @@ object ConfigurationService { if res.toOption.exists(_.contains(oid)) then res else res |+| OdbError.InvalidConfiguration(Some(s"Observation $oid is invalid or has an incomplete configuration.")).asWarning(Map.empty) - private def selectConfigurations(pid: Program.Id)(using Transaction[F]): ResultT[F, Map[Observation.Id, Configuration]] = - ResultT(selectConfigurationsImpl(Queries.selectConfigurations(pid))) - private def selectAllRequestsForProgram(oid: Observation.Id)(using Transaction[F]): ResultT[F, List[ConfigurationRequest]] = ResultT: services.runGraphQLQuery(Queries.selectAllRequestsForProgram(oid)).map: r => @@ -192,8 +189,13 @@ object ConfigurationService { selectConfiguration(input.oid).flatMap(canonicalizeRequest(input, _)) def canonicalizeAll(pid: Program.Id)(using Transaction[F]): ResultT[F, Map[Observation.Id, ConfigurationRequest]] = - selectConfigurations(pid).flatMap: map => - map.toList.traverse((oid, config) => canonicalizeRequest(CreateConfigurationRequestInput(oid), config).tupleLeft(oid)).map(_.toMap) + ResultT + .liftF: + session.prepareR(Statements.SelectActiveNonCalibrations).use: pq => + pq.stream(pid, 1024).compile.toList + .flatMap: oids => + selectConfigurations(oids).flatMap: map => + map.toList.traverse((oid, config) => canonicalizeRequest(CreateConfigurationRequestInput(oid), config).tupleLeft(oid)).map(_.toMap) def updateRequests(SET: ConfigurationRequestPropertiesInput.Update, where: AppliedFragment): ResultT[F, List[ConfigurationRequest.Id]] = // access level has been checked already @@ -842,6 +844,16 @@ object ConfigurationService { void" where c_configuration_request_id in (" |+| which |+| void""") returning c_configuration_request_id """ + + val SelectActiveNonCalibrations: Query[Program.Id, Observation.Id] = + sql""" + select c_observation_id + from t_observation + where c_program_id = $program_id + and c_workflow_user_state is distinct from 'inactive'::e_workflow_user_state + and c_calibration_role is null + """.query(observation_id) + } } diff --git a/modules/service/src/test/scala/lucuma/odb/graphql/mutation/setProposalStatus.scala b/modules/service/src/test/scala/lucuma/odb/graphql/mutation/setProposalStatus.scala index ac938f5d9..f4471fefa 100644 --- a/modules/service/src/test/scala/lucuma/odb/graphql/mutation/setProposalStatus.scala +++ b/modules/service/src/test/scala/lucuma/odb/graphql/mutation/setProposalStatus.scala @@ -10,7 +10,9 @@ import cats.syntax.either.* import cats.syntax.option.* import io.circe.Json import io.circe.literal.* +import lucuma.core.enums.CalibrationRole import lucuma.core.enums.CallForProposalsType +import lucuma.core.enums.ObservationWorkflowState import lucuma.core.enums.Partner import lucuma.core.enums.ProgramType import lucuma.core.model.CallForProposals @@ -543,7 +545,7 @@ class setProposalStatus extends OdbSuite ) } - test("ensure that configuration requests are created when the proposal is submitted") { + test("ensure that configuration requests are created when the proposal is submitted, but not for inactive observations or calibrations") { for cid <- createCallForProposalsAs(staff, CallForProposalsType.RegularSemester) pid <- createProgramAs(pi) @@ -551,6 +553,10 @@ class setProposalStatus extends OdbSuite _ <- addPartnerSplits(pi, pid) tid <- createTargetWithProfileAs(pi, pid) oid <- createGmosNorthLongSlitObservationAs(pi, pid, List(tid)) + ina <- createObservationAs(pi, pid) // inactive, should be ignored + _ <- setObservationWorkflowState(pi, ina, ObservationWorkflowState.Inactive) + cal <- createObservationAs(pi, pid) // calibration, should be ignored + _ <- setObservationCalibratioRole(cal, Some(CalibrationRole.Photometric)) _ <- expect( user = pi,