mirror of
https://github.com/TheAnachronism/docspell.git
synced 2025-04-05 10:59:33 +00:00
Convert equipment record
This commit is contained in:
parent
adee496b77
commit
c5c7f7ed3b
@ -1,3 +1,9 @@
|
|||||||
package docspell.store.impl
|
package docspell.store.impl
|
||||||
|
|
||||||
object Implicits extends DoobieMeta with DoobieSyntax
|
object Implicits extends DoobieMeta with DoobieSyntax {
|
||||||
|
|
||||||
|
implicit final class LegacySyntax(col: docspell.store.qb.Column[_]) {
|
||||||
|
def oldColumn: Column =
|
||||||
|
Column(col.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -26,10 +26,28 @@ trait DSL extends DoobieMeta {
|
|||||||
DBFunction.Count(c, "cn")
|
DBFunction.Count(c, "cn")
|
||||||
|
|
||||||
def and(c: Condition, cs: Condition*): Condition =
|
def and(c: Condition, cs: Condition*): Condition =
|
||||||
Condition.And(c, cs.toVector)
|
c match {
|
||||||
|
case Condition.And(head, tail) =>
|
||||||
|
Condition.And(head, tail ++ (c +: cs.toVector))
|
||||||
|
case _ =>
|
||||||
|
Condition.And(c, cs.toVector)
|
||||||
|
}
|
||||||
|
|
||||||
def or(c: Condition, cs: Condition*): Condition =
|
def or(c: Condition, cs: Condition*): Condition =
|
||||||
Condition.Or(c, cs.toVector)
|
c match {
|
||||||
|
case Condition.Or(head, tail) =>
|
||||||
|
Condition.Or(head, tail ++ (c +: cs.toVector))
|
||||||
|
case _ =>
|
||||||
|
Condition.Or(c, cs.toVector)
|
||||||
|
}
|
||||||
|
|
||||||
|
def not(c: Condition): Condition =
|
||||||
|
c match {
|
||||||
|
case Condition.Not(el) =>
|
||||||
|
el
|
||||||
|
case _ =>
|
||||||
|
Condition.Not(c)
|
||||||
|
}
|
||||||
|
|
||||||
def where(c: Condition, cs: Condition*): Condition =
|
def where(c: Condition, cs: Condition*): Condition =
|
||||||
and(c, cs: _*)
|
and(c, cs: _*)
|
||||||
@ -71,7 +89,27 @@ trait DSL extends DoobieMeta {
|
|||||||
|
|
||||||
def ===(other: Column[A]): Condition =
|
def ===(other: Column[A]): Condition =
|
||||||
Condition.CompareCol(col, Operator.Eq, other)
|
Condition.CompareCol(col, Operator.Eq, other)
|
||||||
|
}
|
||||||
|
|
||||||
|
implicit final class ConditionOps(c: Condition) {
|
||||||
|
|
||||||
|
def &&(other: Condition): Condition =
|
||||||
|
and(c, other)
|
||||||
|
|
||||||
|
def &&?(other: Option[Condition]): Condition =
|
||||||
|
other.map(ce => &&(ce)).getOrElse(c)
|
||||||
|
|
||||||
|
def ||(other: Condition): Condition =
|
||||||
|
or(c, other)
|
||||||
|
|
||||||
|
def ||?(other: Option[Condition]): Condition =
|
||||||
|
other.map(ce => ||(ce)).getOrElse(c)
|
||||||
|
|
||||||
|
def negate: Condition =
|
||||||
|
not(c)
|
||||||
|
|
||||||
|
def unary_! : Condition =
|
||||||
|
not(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -87,13 +87,14 @@ object QItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
def findItem(id: Ident): ConnectionIO[Option[ItemData]] = {
|
def findItem(id: Ident): ConnectionIO[Option[ItemData]] = {
|
||||||
val IC = RItem.Columns.all.map(_.prefix("i"))
|
val equip = REquipment.as("e")
|
||||||
val OC = ROrganization.Columns.all.map(_.prefix("o"))
|
val IC = RItem.Columns.all.map(_.prefix("i"))
|
||||||
val P0C = RPerson.Columns.all.map(_.prefix("p0"))
|
val OC = ROrganization.Columns.all.map(_.prefix("o"))
|
||||||
val P1C = RPerson.Columns.all.map(_.prefix("p1"))
|
val P0C = RPerson.Columns.all.map(_.prefix("p0"))
|
||||||
val EC = REquipment.Columns.all.map(_.prefix("e"))
|
val P1C = RPerson.Columns.all.map(_.prefix("p1"))
|
||||||
val ICC = List(RItem.Columns.id, RItem.Columns.name).map(_.prefix("ref"))
|
val EC = equip.all.map(_.oldColumn).map(_.prefix("e"))
|
||||||
val FC = List(RFolder.Columns.id, RFolder.Columns.name).map(_.prefix("f"))
|
val ICC = List(RItem.Columns.id, RItem.Columns.name).map(_.prefix("ref"))
|
||||||
|
val FC = List(RFolder.Columns.id, RFolder.Columns.name).map(_.prefix("f"))
|
||||||
|
|
||||||
val cq =
|
val cq =
|
||||||
selectSimple(
|
selectSimple(
|
||||||
@ -110,9 +111,11 @@ object QItem {
|
|||||||
fr"LEFT JOIN" ++ RPerson.table ++ fr"p1 ON" ++ RItem.Columns.concPerson
|
fr"LEFT JOIN" ++ RPerson.table ++ fr"p1 ON" ++ RItem.Columns.concPerson
|
||||||
.prefix("i")
|
.prefix("i")
|
||||||
.is(RPerson.Columns.pid.prefix("p1")) ++
|
.is(RPerson.Columns.pid.prefix("p1")) ++
|
||||||
fr"LEFT JOIN" ++ REquipment.table ++ fr"e ON" ++ RItem.Columns.concEquipment
|
fr"LEFT JOIN" ++ Fragment.const(
|
||||||
|
equip.tableName
|
||||||
|
) ++ fr"e ON" ++ RItem.Columns.concEquipment
|
||||||
.prefix("i")
|
.prefix("i")
|
||||||
.is(REquipment.Columns.eid.prefix("e")) ++
|
.is(equip.eid.oldColumn.prefix("e")) ++
|
||||||
fr"LEFT JOIN" ++ RItem.table ++ fr"ref ON" ++ RItem.Columns.inReplyTo
|
fr"LEFT JOIN" ++ RItem.table ++ fr"ref ON" ++ RItem.Columns.inReplyTo
|
||||||
.prefix("i")
|
.prefix("i")
|
||||||
.is(RItem.Columns.id.prefix("ref")) ++
|
.is(RItem.Columns.id.prefix("ref")) ++
|
||||||
@ -305,16 +308,16 @@ object QItem {
|
|||||||
moreCols: Seq[Fragment],
|
moreCols: Seq[Fragment],
|
||||||
ctes: (String, Fragment)*
|
ctes: (String, Fragment)*
|
||||||
): Fragment = {
|
): Fragment = {
|
||||||
|
val equip = REquipment.as("e1")
|
||||||
val IC = RItem.Columns
|
val IC = RItem.Columns
|
||||||
val AC = RAttachment.Columns
|
val AC = RAttachment.Columns
|
||||||
val PC = RPerson.Columns
|
val PC = RPerson.Columns
|
||||||
val OC = ROrganization.Columns
|
val OC = ROrganization.Columns
|
||||||
val EC = REquipment.Columns
|
|
||||||
val FC = RFolder.Columns
|
val FC = RFolder.Columns
|
||||||
val itemCols = IC.all
|
val itemCols = IC.all
|
||||||
val personCols = List(PC.pid, PC.name)
|
val personCols = List(PC.pid, PC.name)
|
||||||
val orgCols = List(OC.oid, OC.name)
|
val orgCols = List(OC.oid, OC.name)
|
||||||
val equipCols = List(EC.eid, EC.name)
|
val equipCols = List(equip.eid.oldColumn, equip.name.oldColumn)
|
||||||
val folderCols = List(FC.id, FC.name)
|
val folderCols = List(FC.id, FC.name)
|
||||||
val cvItem = RCustomFieldValue.Columns.itemId.prefix("cv")
|
val cvItem = RCustomFieldValue.Columns.itemId.prefix("cv")
|
||||||
|
|
||||||
@ -335,8 +338,8 @@ object QItem {
|
|||||||
PC.name.prefix("p0").f,
|
PC.name.prefix("p0").f,
|
||||||
PC.pid.prefix("p1").f,
|
PC.pid.prefix("p1").f,
|
||||||
PC.name.prefix("p1").f,
|
PC.name.prefix("p1").f,
|
||||||
EC.eid.prefix("e1").f,
|
equip.eid.oldColumn.prefix("e1").f,
|
||||||
EC.name.prefix("e1").f,
|
equip.name.oldColumn.prefix("e1").f,
|
||||||
FC.id.prefix("f1").f,
|
FC.id.prefix("f1").f,
|
||||||
FC.name.prefix("f1").f,
|
FC.name.prefix("f1").f,
|
||||||
// sql uses 1 for first character
|
// sql uses 1 for first character
|
||||||
@ -357,7 +360,11 @@ object QItem {
|
|||||||
val withOrgs =
|
val withOrgs =
|
||||||
selectSimple(orgCols, ROrganization.table, OC.cid.is(q.account.collective))
|
selectSimple(orgCols, ROrganization.table, OC.cid.is(q.account.collective))
|
||||||
val withEquips =
|
val withEquips =
|
||||||
selectSimple(equipCols, REquipment.table, EC.cid.is(q.account.collective))
|
selectSimple(
|
||||||
|
equipCols,
|
||||||
|
Fragment.const(equip.tableName),
|
||||||
|
equip.cid.oldColumn.is(q.account.collective)
|
||||||
|
)
|
||||||
val withFolder =
|
val withFolder =
|
||||||
selectSimple(folderCols, RFolder.table, FC.collective.is(q.account.collective))
|
selectSimple(folderCols, RFolder.table, FC.collective.is(q.account.collective))
|
||||||
val withAttach = fr"SELECT COUNT(" ++ AC.id.f ++ fr") as num, " ++ AC.itemId.f ++
|
val withAttach = fr"SELECT COUNT(" ++ AC.id.f ++ fr") as num, " ++ AC.itemId.f ++
|
||||||
@ -384,7 +391,7 @@ object QItem {
|
|||||||
fr"LEFT JOIN persons p1 ON" ++ IC.concPerson.prefix("i").is(PC.pid.prefix("p1")) ++
|
fr"LEFT JOIN persons p1 ON" ++ IC.concPerson.prefix("i").is(PC.pid.prefix("p1")) ++
|
||||||
fr"LEFT JOIN equips e1 ON" ++ IC.concEquipment
|
fr"LEFT JOIN equips e1 ON" ++ IC.concEquipment
|
||||||
.prefix("i")
|
.prefix("i")
|
||||||
.is(EC.eid.prefix("e1")) ++
|
.is(equip.eid.oldColumn.prefix("e1")) ++
|
||||||
fr"LEFT JOIN folders f1 ON" ++ IC.folder.prefix("i").is(FC.id.prefix("f1")) ++
|
fr"LEFT JOIN folders f1 ON" ++ IC.folder.prefix("i").is(FC.id.prefix("f1")) ++
|
||||||
(if (q.customValues.isEmpty) Fragment.empty
|
(if (q.customValues.isEmpty) Fragment.empty
|
||||||
else
|
else
|
||||||
@ -396,10 +403,10 @@ object QItem {
|
|||||||
maxNoteLen: Int,
|
maxNoteLen: Int,
|
||||||
batch: Batch
|
batch: Batch
|
||||||
): Stream[ConnectionIO, ListItem] = {
|
): Stream[ConnectionIO, ListItem] = {
|
||||||
val IC = RItem.Columns
|
val equip = REquipment.as("e1")
|
||||||
val PC = RPerson.Columns
|
val IC = RItem.Columns
|
||||||
val OC = ROrganization.Columns
|
val PC = RPerson.Columns
|
||||||
val EC = REquipment.Columns
|
val OC = ROrganization.Columns
|
||||||
|
|
||||||
// inclusive tags are AND-ed
|
// inclusive tags are AND-ed
|
||||||
val tagSelectsIncl = q.tagsInclude
|
val tagSelectsIncl = q.tagsInclude
|
||||||
@ -432,7 +439,7 @@ object QItem {
|
|||||||
OC.name.prefix("o0").lowerLike(n),
|
OC.name.prefix("o0").lowerLike(n),
|
||||||
PC.name.prefix("p0").lowerLike(n),
|
PC.name.prefix("p0").lowerLike(n),
|
||||||
PC.name.prefix("p1").lowerLike(n),
|
PC.name.prefix("p1").lowerLike(n),
|
||||||
EC.name.prefix("e1").lowerLike(n),
|
equip.name.oldColumn.prefix("e1").lowerLike(n),
|
||||||
IC.name.prefix("i").lowerLike(n),
|
IC.name.prefix("i").lowerLike(n),
|
||||||
IC.notes.prefix("i").lowerLike(n)
|
IC.notes.prefix("i").lowerLike(n)
|
||||||
)
|
)
|
||||||
@ -441,7 +448,7 @@ object QItem {
|
|||||||
RPerson.Columns.pid.prefix("p0").isOrDiscard(q.corrPerson),
|
RPerson.Columns.pid.prefix("p0").isOrDiscard(q.corrPerson),
|
||||||
ROrganization.Columns.oid.prefix("o0").isOrDiscard(q.corrOrg),
|
ROrganization.Columns.oid.prefix("o0").isOrDiscard(q.corrOrg),
|
||||||
RPerson.Columns.pid.prefix("p1").isOrDiscard(q.concPerson),
|
RPerson.Columns.pid.prefix("p1").isOrDiscard(q.concPerson),
|
||||||
REquipment.Columns.eid.prefix("e1").isOrDiscard(q.concEquip),
|
equip.eid.oldColumn.prefix("e1").isOrDiscard(q.concEquip),
|
||||||
RFolder.Columns.id.prefix("f1").isOrDiscard(q.folder),
|
RFolder.Columns.id.prefix("f1").isOrDiscard(q.folder),
|
||||||
if (q.tagsInclude.isEmpty && q.tagCategoryIncl.isEmpty) Fragment.empty
|
if (q.tagsInclude.isEmpty && q.tagCategoryIncl.isEmpty) Fragment.empty
|
||||||
else
|
else
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package docspell.store.records
|
package docspell.store.records
|
||||||
|
|
||||||
import docspell.common._
|
import docspell.common._
|
||||||
import docspell.store.impl.Implicits._
|
import docspell.store.qb.DSL._
|
||||||
import docspell.store.impl._
|
import docspell.store.qb._
|
||||||
|
|
||||||
import doobie._
|
import doobie._
|
||||||
import doobie.implicits._
|
import doobie.implicits._
|
||||||
@ -16,70 +16,85 @@ case class REquipment(
|
|||||||
) {}
|
) {}
|
||||||
|
|
||||||
object REquipment {
|
object REquipment {
|
||||||
|
final case class Table(alias: Option[String]) extends TableDef {
|
||||||
|
val tableName = "equipment"
|
||||||
|
|
||||||
val table = fr"equipment"
|
val eid = Column[Ident]("eid", this)
|
||||||
|
val cid = Column[Ident]("cid", this)
|
||||||
object Columns {
|
val name = Column[String]("name", this)
|
||||||
val eid = Column("eid")
|
val created = Column[Timestamp]("created", this)
|
||||||
val cid = Column("cid")
|
val updated = Column[Timestamp]("updated", this)
|
||||||
val name = Column("name")
|
|
||||||
val created = Column("created")
|
|
||||||
val updated = Column("updated")
|
|
||||||
val all = List(eid, cid, name, created, updated)
|
val all = List(eid, cid, name, created, updated)
|
||||||
}
|
}
|
||||||
import Columns._
|
|
||||||
|
def as(alias: String): Table =
|
||||||
|
Table(Some(alias))
|
||||||
|
|
||||||
def insert(v: REquipment): ConnectionIO[Int] = {
|
def insert(v: REquipment): ConnectionIO[Int] = {
|
||||||
val sql =
|
val t = Table(None)
|
||||||
insertRow(table, all, fr"${v.eid},${v.cid},${v.name},${v.created},${v.updated}")
|
DML
|
||||||
sql.update.run
|
.insert(
|
||||||
|
t,
|
||||||
|
t.all,
|
||||||
|
fr"${v.eid},${v.cid},${v.name},${v.created},${v.updated}"
|
||||||
|
)
|
||||||
|
.update
|
||||||
|
.run
|
||||||
}
|
}
|
||||||
|
|
||||||
def update(v: REquipment): ConnectionIO[Int] = {
|
def update(v: REquipment): ConnectionIO[Int] = {
|
||||||
def sql(now: Timestamp) =
|
val t = Table(None)
|
||||||
updateRow(
|
|
||||||
table,
|
|
||||||
and(eid.is(v.eid), cid.is(v.cid)),
|
|
||||||
commas(
|
|
||||||
cid.setTo(v.cid),
|
|
||||||
name.setTo(v.name),
|
|
||||||
updated.setTo(now)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
for {
|
for {
|
||||||
now <- Timestamp.current[ConnectionIO]
|
now <- Timestamp.current[ConnectionIO]
|
||||||
n <- sql(now).update.run
|
n <- DML
|
||||||
|
.update(
|
||||||
|
t,
|
||||||
|
where(t.eid === v.eid, t.cid === v.cid),
|
||||||
|
DML.set(
|
||||||
|
t.cid.setTo(v.cid),
|
||||||
|
t.name.setTo(v.name),
|
||||||
|
t.updated.setTo(now)
|
||||||
|
)
|
||||||
|
)
|
||||||
} yield n
|
} yield n
|
||||||
}
|
}
|
||||||
|
|
||||||
def existsByName(coll: Ident, ename: String): ConnectionIO[Boolean] = {
|
def existsByName(coll: Ident, ename: String): ConnectionIO[Boolean] = {
|
||||||
val sql = selectCount(eid, table, and(cid.is(coll), name.is(ename)))
|
val t = Table(None)
|
||||||
|
val sql = run(select(count(t.eid)), from(t), where(t.cid === coll, t.name === ename))
|
||||||
sql.query[Int].unique.map(_ > 0)
|
sql.query[Int].unique.map(_ > 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
def findById(id: Ident): ConnectionIO[Option[REquipment]] = {
|
def findById(id: Ident): ConnectionIO[Option[REquipment]] = {
|
||||||
val sql = selectSimple(all, table, eid.is(id))
|
val t = Table(None)
|
||||||
|
val sql = run(select(t.all), from(t), t.eid === id)
|
||||||
sql.query[REquipment].option
|
sql.query[REquipment].option
|
||||||
}
|
}
|
||||||
|
|
||||||
def findAll(
|
def findAll(
|
||||||
coll: Ident,
|
coll: Ident,
|
||||||
nameQ: Option[String],
|
nameQ: Option[String],
|
||||||
order: Columns.type => Column
|
order: Table => Column[_]
|
||||||
): ConnectionIO[Vector[REquipment]] = {
|
): ConnectionIO[Vector[REquipment]] = {
|
||||||
val q = Seq(cid.is(coll)) ++ (nameQ match {
|
val t = Table(None)
|
||||||
case Some(str) => Seq(name.lowerLike(s"%${str.toLowerCase}%"))
|
|
||||||
case None => Seq.empty
|
val q = t.cid === coll &&? nameQ
|
||||||
})
|
.map(str => s"%${str.toLowerCase}%")
|
||||||
val sql = selectSimple(all, table, and(q)) ++ orderBy(order(Columns).f)
|
.map(v => t.name.like(v))
|
||||||
|
|
||||||
|
val sql = Select(select(t.all), from(t), q).orderBy(order(t)).run
|
||||||
sql.query[REquipment].to[Vector]
|
sql.query[REquipment].to[Vector]
|
||||||
}
|
}
|
||||||
|
|
||||||
def findLike(coll: Ident, equipName: String): ConnectionIO[Vector[IdRef]] =
|
def findLike(coll: Ident, equipName: String): ConnectionIO[Vector[IdRef]] = {
|
||||||
selectSimple(List(eid, name), table, and(cid.is(coll), name.lowerLike(equipName)))
|
val t = Table(None)
|
||||||
|
run(select(List(t.eid, t.name)), from(t), t.cid === coll && t.name.like(equipName))
|
||||||
.query[IdRef]
|
.query[IdRef]
|
||||||
.to[Vector]
|
.to[Vector]
|
||||||
|
}
|
||||||
|
|
||||||
def delete(id: Ident, coll: Ident): ConnectionIO[Int] =
|
def delete(id: Ident, coll: Ident): ConnectionIO[Int] = {
|
||||||
deleteFrom(table, and(eid.is(id), cid.is(coll))).update.run
|
val t = Table(None)
|
||||||
|
DML.delete(t, t.eid === id && t.cid === coll).update.run
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user