From 0229a867af2c98a1ccbb9bec911a7c4842d8de3b Mon Sep 17 00:00:00 2001 From: Eike Kettner <eike.kettner@posteo.de> Date: Wed, 10 Mar 2021 22:16:04 +0100 Subject: [PATCH] Add a use colum to metadata entities --- .../scala/docspell/common/EquipmentUse.scala | 46 +++++++++++++++++++ .../main/scala/docspell/common/OrgUse.scala | 46 +++++++++++++++++++ .../scala/docspell/common/PersonUse.scala | 3 ++ .../docspell/joex/process/FindProposal.scala | 23 ++++++++-- .../restserver/conv/Conversions.scala | 10 ++-- .../migration/h2/V1.21.1__equip_org_use.sql | 16 +++++++ .../mariadb/V1.21.1__equip_org_use.sql | 16 +++++++ .../postgresql/V1.21.1__equip_org_use.sql | 16 +++++++ .../docspell/store/impl/DoobieMeta.scala | 6 +++ .../docspell/store/records/REquipment.scala | 23 +++++++--- .../store/records/ROrganization.scala | 22 ++++++--- .../webapp/src/main/elm/Comp/PersonForm.elm | 3 ++ .../webapp/src/main/elm/Data/PersonUse.elm | 15 +++++- 13 files changed, 223 insertions(+), 22 deletions(-) create mode 100644 modules/common/src/main/scala/docspell/common/EquipmentUse.scala create mode 100644 modules/common/src/main/scala/docspell/common/OrgUse.scala create mode 100644 modules/store/src/main/resources/db/migration/h2/V1.21.1__equip_org_use.sql create mode 100644 modules/store/src/main/resources/db/migration/mariadb/V1.21.1__equip_org_use.sql create mode 100644 modules/store/src/main/resources/db/migration/postgresql/V1.21.1__equip_org_use.sql diff --git a/modules/common/src/main/scala/docspell/common/EquipmentUse.scala b/modules/common/src/main/scala/docspell/common/EquipmentUse.scala new file mode 100644 index 00000000..9841da59 --- /dev/null +++ b/modules/common/src/main/scala/docspell/common/EquipmentUse.scala @@ -0,0 +1,46 @@ +package docspell.common + +import cats.data.NonEmptyList + +import io.circe.Decoder +import io.circe.Encoder + +sealed trait EquipmentUse { self: Product => + + final def name: String = + self.productPrefix.toLowerCase() +} + +object EquipmentUse { + + case object Concerning extends EquipmentUse + case object Disabled extends EquipmentUse + + def concerning: EquipmentUse = Concerning + def disabled: EquipmentUse = Disabled + + val all: NonEmptyList[EquipmentUse] = + NonEmptyList.of(concerning, disabled) + + val notDisabled: NonEmptyList[EquipmentUse] = + NonEmptyList.of(concerning) + + def fromString(str: String): Either[String, EquipmentUse] = + str.toLowerCase() match { + case "concerning" => + Right(Concerning) + case "disabled" => + Right(Disabled) + case _ => + Left(s"Unknown equipment-use: $str") + } + + def unsafeFromString(str: String): EquipmentUse = + fromString(str).fold(sys.error, identity) + + implicit val jsonDecoder: Decoder[EquipmentUse] = + Decoder.decodeString.emap(fromString) + + implicit val jsonEncoder: Encoder[EquipmentUse] = + Encoder.encodeString.contramap(_.name) +} diff --git a/modules/common/src/main/scala/docspell/common/OrgUse.scala b/modules/common/src/main/scala/docspell/common/OrgUse.scala new file mode 100644 index 00000000..fc2f803e --- /dev/null +++ b/modules/common/src/main/scala/docspell/common/OrgUse.scala @@ -0,0 +1,46 @@ +package docspell.common + +import cats.data.NonEmptyList + +import io.circe.Decoder +import io.circe.Encoder + +sealed trait OrgUse { self: Product => + + final def name: String = + self.productPrefix.toLowerCase() +} + +object OrgUse { + + case object Correspondent extends OrgUse + case object Disabled extends OrgUse + + def correspondent: OrgUse = Correspondent + def disabled: OrgUse = Disabled + + val all: NonEmptyList[OrgUse] = + NonEmptyList.of(correspondent, disabled) + + val notDisabled: NonEmptyList[OrgUse] = + NonEmptyList.of(correspondent) + + def fromString(str: String): Either[String, OrgUse] = + str.toLowerCase() match { + case "correspondent" => + Right(Correspondent) + case "disabled" => + Right(Disabled) + case _ => + Left(s"Unknown organization-use: $str") + } + + def unsafeFromString(str: String): OrgUse = + fromString(str).fold(sys.error, identity) + + implicit val jsonDecoder: Decoder[OrgUse] = + Decoder.decodeString.emap(fromString) + + implicit val jsonEncoder: Encoder[OrgUse] = + Encoder.encodeString.contramap(_.name) +} diff --git a/modules/common/src/main/scala/docspell/common/PersonUse.scala b/modules/common/src/main/scala/docspell/common/PersonUse.scala index 71cd3365..d070425e 100644 --- a/modules/common/src/main/scala/docspell/common/PersonUse.scala +++ b/modules/common/src/main/scala/docspell/common/PersonUse.scala @@ -16,6 +16,7 @@ object PersonUse { case object Correspondent extends PersonUse case object Concerning extends PersonUse case object Both extends PersonUse + case object Disabled extends PersonUse def concerning: PersonUse = Concerning def correspondent: PersonUse = Correspondent @@ -35,6 +36,8 @@ object PersonUse { Right(Concerning) case "both" => Right(Both) + case "disabled" => + Right(Disabled) case _ => Left(s"Unknown person-use: $str") } diff --git a/modules/joex/src/main/scala/docspell/joex/process/FindProposal.scala b/modules/joex/src/main/scala/docspell/joex/process/FindProposal.scala index 42bbb536..a159ad34 100644 --- a/modules/joex/src/main/scala/docspell/joex/process/FindProposal.scala +++ b/modules/joex/src/main/scala/docspell/joex/process/FindProposal.scala @@ -47,7 +47,7 @@ object FindProposal { ctx.store .transact( ROrganization - .findLike(coll, mp.values.head.ref.name.toLowerCase) + .findLike(coll, mp.values.head.ref.name.toLowerCase, OrgUse.notDisabled) .map(_.headOption) ) .flatTap(oref => @@ -85,7 +85,11 @@ object FindProposal { ctx.store .transact( REquipment - .findLike(coll, mp.values.head.ref.name.toLowerCase) + .findLike( + coll, + mp.values.head.ref.name.toLowerCase, + EquipmentUse.notDisabled + ) .map(_.headOption) ) .flatTap(oref => @@ -234,7 +238,10 @@ object FindProposal { case NerTag.Organization => ctx.logger.debug(s"Looking for organizations: $value") *> ctx.store - .transact(ROrganization.findLike(ctx.args.meta.collective, value)) + .transact( + ROrganization + .findLike(ctx.args.meta.collective, value, OrgUse.notDisabled) + ) .map(MetaProposalList.from(MetaProposalType.CorrOrg, nt)) case NerTag.Person => @@ -252,7 +259,10 @@ object FindProposal { .map(MetaProposalList.from(MetaProposalType.CorrPerson, nt)) val s3 = ctx.store - .transact(ROrganization.findLike(ctx.args.meta.collective, value)) + .transact( + ROrganization + .findLike(ctx.args.meta.collective, value, OrgUse.notDisabled) + ) .map(MetaProposalList.from(MetaProposalType.CorrOrg, nt)) ctx.logger.debug(s"Looking for persons and organizations: $value") *> (for { ml0 <- s1 @@ -268,7 +278,10 @@ object FindProposal { case NerTag.Misc => ctx.logger.debug(s"Looking for equipments: $value") *> ctx.store - .transact(REquipment.findLike(ctx.args.meta.collective, value)) + .transact( + REquipment + .findLike(ctx.args.meta.collective, value, EquipmentUse.notDisabled) + ) .map(MetaProposalList.from(MetaProposalType.ConcEquip, nt)) case NerTag.Email => diff --git a/modules/restserver/src/main/scala/docspell/restserver/conv/Conversions.scala b/modules/restserver/src/main/scala/docspell/restserver/conv/Conversions.scala index cede3845..55531fff 100644 --- a/modules/restserver/src/main/scala/docspell/restserver/conv/Conversions.scala +++ b/modules/restserver/src/main/scala/docspell/restserver/conv/Conversions.scala @@ -414,7 +414,8 @@ trait Conversions { v.notes, now, now, - v.shortName.map(_.trim) + v.shortName.map(_.trim), + OrgUse.Correspondent ) } yield OOrganization.OrgAndContacts(org, cont) } @@ -439,7 +440,8 @@ trait Conversions { v.notes, v.created, now, - v.shortName.map(_.trim) + v.shortName.map(_.trim), + OrgUse.Correspondent ) } yield OOrganization.OrgAndContacts(org, cont) } @@ -632,13 +634,13 @@ trait Conversions { def newEquipment[F[_]: Sync](e: Equipment, cid: Ident): F[REquipment] = timeId.map({ case (id, now) => - REquipment(id, cid, e.name.trim, now, now, e.notes) + REquipment(id, cid, e.name.trim, now, now, e.notes, EquipmentUse.Concerning) }) def changeEquipment[F[_]: Sync](e: Equipment, cid: Ident): F[REquipment] = Timestamp .current[F] - .map(now => REquipment(e.id, cid, e.name.trim, e.created, now, e.notes)) + .map(now => REquipment(e.id, cid, e.name.trim, e.created, now, e.notes, EquipmentUse.Concerning)) // idref diff --git a/modules/store/src/main/resources/db/migration/h2/V1.21.1__equip_org_use.sql b/modules/store/src/main/resources/db/migration/h2/V1.21.1__equip_org_use.sql new file mode 100644 index 00000000..80069ac3 --- /dev/null +++ b/modules/store/src/main/resources/db/migration/h2/V1.21.1__equip_org_use.sql @@ -0,0 +1,16 @@ +ALTER TABLE "equipment" +ADD COLUMN "equip_use" varchar(254); + +UPDATE "equipment" SET "equip_use" = 'concerning'; + +ALTER TABLE "equipment" +ALTER COLUMN "equip_use" SET NOT NULL; + + +ALTER TABLE "organization" +ADD COLUMN "org_use" varchar(254); + +UPDATE "organization" SET "org_use" = 'correspondent'; + +ALTER TABLE "organization" +ALTER COLUMN "org_use" SET NOT NULL; diff --git a/modules/store/src/main/resources/db/migration/mariadb/V1.21.1__equip_org_use.sql b/modules/store/src/main/resources/db/migration/mariadb/V1.21.1__equip_org_use.sql new file mode 100644 index 00000000..8f32937a --- /dev/null +++ b/modules/store/src/main/resources/db/migration/mariadb/V1.21.1__equip_org_use.sql @@ -0,0 +1,16 @@ +ALTER TABLE `equipment` +ADD COLUMN `equip_use` varchar(254); + +UPDATE `equipment` SET `equip_use` = 'concerning'; + +ALTER TABLE `equipment` +ALTER COLUMN `equip_use` SET NOT NULL; + + +ALTER TABLE `organization` +ADD COLUMN `org_use` varchar(254); + +UPDATE `organization` SET `org_use` = 'correspondent'; + +ALTER TABLE `organization` +ALTER COLUMN `org_use` SET NOT NULL; diff --git a/modules/store/src/main/resources/db/migration/postgresql/V1.21.1__equip_org_use.sql b/modules/store/src/main/resources/db/migration/postgresql/V1.21.1__equip_org_use.sql new file mode 100644 index 00000000..80069ac3 --- /dev/null +++ b/modules/store/src/main/resources/db/migration/postgresql/V1.21.1__equip_org_use.sql @@ -0,0 +1,16 @@ +ALTER TABLE "equipment" +ADD COLUMN "equip_use" varchar(254); + +UPDATE "equipment" SET "equip_use" = 'concerning'; + +ALTER TABLE "equipment" +ALTER COLUMN "equip_use" SET NOT NULL; + + +ALTER TABLE "organization" +ADD COLUMN "org_use" varchar(254); + +UPDATE "organization" SET "org_use" = 'correspondent'; + +ALTER TABLE "organization" +ALTER COLUMN "org_use" SET NOT NULL; diff --git a/modules/store/src/main/scala/docspell/store/impl/DoobieMeta.scala b/modules/store/src/main/scala/docspell/store/impl/DoobieMeta.scala index e38e8334..e15da7ae 100644 --- a/modules/store/src/main/scala/docspell/store/impl/DoobieMeta.scala +++ b/modules/store/src/main/scala/docspell/store/impl/DoobieMeta.scala @@ -106,6 +106,12 @@ trait DoobieMeta extends EmilDoobieMeta { implicit val metaPersonUse: Meta[PersonUse] = Meta[String].timap(PersonUse.unsafeFromString)(_.name) + + implicit val metaEquipUse: Meta[EquipmentUse] = + Meta[String].timap(EquipmentUse.unsafeFromString)(_.name) + + implicit val metaOrgUse: Meta[OrgUse] = + Meta[String].timap(OrgUse.unsafeFromString)(_.name) } object DoobieMeta extends DoobieMeta { diff --git a/modules/store/src/main/scala/docspell/store/records/REquipment.scala b/modules/store/src/main/scala/docspell/store/records/REquipment.scala index 5befc011..6cb31224 100644 --- a/modules/store/src/main/scala/docspell/store/records/REquipment.scala +++ b/modules/store/src/main/scala/docspell/store/records/REquipment.scala @@ -15,7 +15,8 @@ case class REquipment( name: String, created: Timestamp, updated: Timestamp, - notes: Option[String] + notes: Option[String], + use: EquipmentUse ) {} object REquipment { @@ -28,7 +29,8 @@ object REquipment { val created = Column[Timestamp]("created", this) val updated = Column[Timestamp]("updated", this) val notes = Column[String]("notes", this) - val all = NonEmptyList.of[Column[_]](eid, cid, name, created, updated, notes) + val use = Column[EquipmentUse]("equip_use", this) + val all = NonEmptyList.of[Column[_]](eid, cid, name, created, updated, notes, use) } val T = Table(None) @@ -41,7 +43,7 @@ object REquipment { .insert( t, t.all, - fr"${v.eid},${v.cid},${v.name},${v.created},${v.updated},${v.notes}" + fr"${v.eid},${v.cid},${v.name},${v.created},${v.updated},${v.notes},${v.use}" ) } @@ -57,7 +59,8 @@ object REquipment { t.cid.setTo(v.cid), t.name.setTo(v.name), t.updated.setTo(now), - t.notes.setTo(v.notes) + t.notes.setTo(v.notes), + t.use.setTo(v.use) ) ) } yield n @@ -90,9 +93,17 @@ object REquipment { sql.query[REquipment].to[Vector] } - def findLike(coll: Ident, equipName: String): ConnectionIO[Vector[IdRef]] = { + def findLike( + coll: Ident, + equipName: String, + use: NonEmptyList[EquipmentUse] + ): ConnectionIO[Vector[IdRef]] = { val t = Table(None) - run(select(t.eid, t.name), from(t), t.cid === coll && t.name.like(equipName)) + run( + select(t.eid, t.name), + from(t), + t.cid === coll && t.name.like(equipName) && t.use.in(use) + ) .query[IdRef] .to[Vector] } diff --git a/modules/store/src/main/scala/docspell/store/records/ROrganization.scala b/modules/store/src/main/scala/docspell/store/records/ROrganization.scala index 339c07e3..bbf4e385 100644 --- a/modules/store/src/main/scala/docspell/store/records/ROrganization.scala +++ b/modules/store/src/main/scala/docspell/store/records/ROrganization.scala @@ -22,7 +22,8 @@ case class ROrganization( notes: Option[String], created: Timestamp, updated: Timestamp, - shortName: Option[String] + shortName: Option[String], + use: OrgUse ) {} object ROrganization { @@ -43,6 +44,7 @@ object ROrganization { val created = Column[Timestamp]("created", this) val updated = Column[Timestamp]("updated", this) val shortName = Column[String]("short_name", this) + val use = Column[OrgUse]("org_use", this) val all = NonEmptyList.of[Column[_]]( oid, @@ -55,7 +57,8 @@ object ROrganization { notes, created, updated, - shortName + shortName, + use ) } @@ -67,7 +70,7 @@ object ROrganization { DML.insert( T, T.all, - fr"${v.oid},${v.cid},${v.name},${v.street},${v.zip},${v.city},${v.country},${v.notes},${v.created},${v.updated},${v.shortName}" + fr"${v.oid},${v.cid},${v.name},${v.street},${v.zip},${v.city},${v.country},${v.notes},${v.created},${v.updated},${v.shortName},${v.use}" ) def update(v: ROrganization): ConnectionIO[Int] = { @@ -84,7 +87,8 @@ object ROrganization { T.country.setTo(v.country), T.notes.setTo(v.notes), T.updated.setTo(now), - T.shortName.setTo(v.shortName) + T.shortName.setTo(v.shortName), + T.use.setTo(v.use) ) ) for { @@ -109,11 +113,17 @@ object ROrganization { sql.query[ROrganization].option } - def findLike(coll: Ident, orgName: String): ConnectionIO[Vector[IdRef]] = + def findLike( + coll: Ident, + orgName: String, + use: NonEmptyList[OrgUse] + ): ConnectionIO[Vector[IdRef]] = run( select(T.oid, T.name), from(T), - T.cid === coll && (T.name.like(orgName) || T.shortName.like(orgName)) + T.cid === coll && (T.name.like(orgName) || T.shortName.like(orgName)) && T.use.in( + use + ) ) .query[IdRef] .to[Vector] diff --git a/modules/webapp/src/main/elm/Comp/PersonForm.elm b/modules/webapp/src/main/elm/Comp/PersonForm.elm index 004157db..e9b35c79 100644 --- a/modules/webapp/src/main/elm/Comp/PersonForm.elm +++ b/modules/webapp/src/main/elm/Comp/PersonForm.elm @@ -229,6 +229,9 @@ view2 mobile settings model = Data.PersonUse.Both -> text "Use as both concerning or correspondent person" + + Data.PersonUse.Disabled -> + text "Do not use for suggestions." ] ] , div [ class "mb-4" ] diff --git a/modules/webapp/src/main/elm/Data/PersonUse.elm b/modules/webapp/src/main/elm/Data/PersonUse.elm index c00342a4..fc5d2060 100644 --- a/modules/webapp/src/main/elm/Data/PersonUse.elm +++ b/modules/webapp/src/main/elm/Data/PersonUse.elm @@ -14,6 +14,7 @@ type PersonUse = Correspondent | Concerning | Both + | Disabled fromString : String -> Maybe PersonUse @@ -28,6 +29,9 @@ fromString str = "both" -> Just Both + "disabled" -> + Just Disabled + _ -> Nothing @@ -44,6 +48,9 @@ asString pu = Both -> "both" + Disabled -> + "disabled" + label : PersonUse -> String label pu = @@ -57,10 +64,13 @@ label pu = Both -> "Both" + Disabled -> + "Disabled" + all : List PersonUse all = - [ Correspondent, Concerning, Both ] + [ Correspondent, Concerning, Both, Disabled ] spanPersonList : List Person -> { concerning : List Person, correspondent : List Person } @@ -86,5 +96,8 @@ spanPersonList input = | correspondent = p :: res.correspondent , concerning = p :: res.concerning } + + Disabled -> + res in List.foldl merge init input