Update state and proposals only on invalid items

Invalid items are those that are not ready, and not shown to the user.
When changing metadata, it should only be changed, if the item was not
already shown to the user.
This commit is contained in:
Eike Kettner 2020-05-23 15:46:24 +02:00
parent 855d4eefa8
commit 25d089da6c
6 changed files with 48 additions and 23 deletions

View File

@ -1,11 +1,18 @@
package docspell.common
import io.circe.{Decoder, Encoder}
import cats.data.NonEmptyList
sealed trait ItemState { self: Product =>
final def name: String =
productPrefix.toLowerCase
def isValid: Boolean =
ItemState.validStates.exists(_ == this)
def isInvalid: Boolean =
ItemState.invalidStates.exists(_ == this)
}
object ItemState {
@ -24,8 +31,11 @@ object ItemState {
case _ => Left(s"Invalid item state: $str")
}
val validStates: Seq[ItemState] =
Seq(Created, Confirmed)
val validStates: NonEmptyList[ItemState] =
NonEmptyList.of(Created, Confirmed)
val invalidStates: NonEmptyList[ItemState] =
NonEmptyList.of(Premature, Processing)
def unsafe(str: String): ItemState =
fromString(str).fold(sys.error, identity)

View File

@ -71,7 +71,7 @@ object NotifyDueItemsTask {
QItem.Query
.empty(ctx.args.account.collective)
.copy(
states = ItemState.validStates,
states = ItemState.validStates.toList,
tagsInclude = ctx.args.tagsInclude,
tagsExclude = ctx.args.tagsExclude,
dueDateFrom = ctx.args.daysBack.map(back => now - Duration.days(back.toLong)),

View File

@ -25,7 +25,11 @@ object ItemHandler {
def itemStateTask[F[_]: Sync, A](
state: ItemState
)(data: ItemData): Task[F, A, ItemData] =
Task(ctx => ctx.store.transact(RItem.updateState(data.item.id, state)).map(_ => data))
Task(ctx =>
ctx.store
.transact(RItem.updateState(data.item.id, state, ItemState.invalidStates))
.map(_ => data)
)
def isLastRetry[F[_]: Sync, A](ctx: Context[F, A]): F[Boolean] =
for {

View File

@ -9,21 +9,26 @@ import docspell.store.records.RItem
object LinkProposal {
def apply[F[_]: Sync](data: ItemData): Task[F, ProcessItemArgs, ItemData] =
Task { ctx =>
// sort by weight; order of equal weights is not important, just
// choose one others are then suggestions
// doc-date is only set when given explicitely, not from "guessing"
val proposals = MetaProposalList
.flatten(data.metas.map(_.proposals))
.filter(_.proposalType != MetaProposalType.DocDate)
.sortByWeights
if (data.item.state.isValid)
Task
.log[F, ProcessItemArgs](_.debug(s"Not linking proposals on existing item"))
.map(_ => data)
else
Task { ctx =>
// sort by weight; order of equal weights is not important, just
// choose one others are then suggestions
// doc-date is only set when given explicitely, not from "guessing"
val proposals = MetaProposalList
.flatten(data.metas.map(_.proposals))
.filter(_.proposalType != MetaProposalType.DocDate)
.sortByWeights
ctx.logger.info(s"Starting linking proposals") *>
MetaProposalType.all
.traverse(applyValue(data, proposals, ctx))
.map(result => ctx.logger.info(s"Results from proposal processing: $result"))
.map(_ => data)
}
ctx.logger.info(s"Starting linking proposals") *>
MetaProposalType.all
.traverse(applyValue(data, proposals, ctx))
.map(result => ctx.logger.info(s"Results from proposal processing: $result"))
.map(_ => data)
}
def applyValue[F[_]: Sync](
data: ItemData,
@ -40,8 +45,9 @@ object LinkProposal {
Result.single(mpt)
)
case Some(a) =>
val ids = a.values.map(_.ref.id.id)
ctx.logger.info(
s"Found many (${a.size}, ${a.values.map(_.ref.id.id)}) candidates for ${a.proposalType}. Setting first."
s"Found many (${a.size}, ${ids}) candidates for ${a.proposalType}. Setting first."
) *>
setItemMeta(data.item.id, ctx, a.proposalType, a.values.head.ref.id).map(_ =>
Result.multiple(mpt)

View File

@ -109,7 +109,7 @@ trait Conversions {
coll,
m.name,
if (m.inbox) Seq(ItemState.Created)
else ItemState.validStates,
else ItemState.validStates.toList,
m.direction,
m.corrPerson,
m.corrOrg,

View File

@ -1,7 +1,8 @@
package docspell.store.records
import cats.implicits._
import cats.data.NonEmptyList
import cats.effect.Sync
import cats.implicits._
import doobie._
import doobie.implicits._
import docspell.common._
@ -110,12 +111,16 @@ object RItem {
def getCollective(itemId: Ident): ConnectionIO[Option[Ident]] =
selectSimple(List(cid), table, id.is(itemId)).query[Ident].option
def updateState(itemId: Ident, itemState: ItemState): ConnectionIO[Int] =
def updateState(
itemId: Ident,
itemState: ItemState,
existing: NonEmptyList[ItemState]
): ConnectionIO[Int] =
for {
t <- currentTime
n <- updateRow(
table,
id.is(itemId),
and(id.is(itemId), state.isIn(existing)),
commas(state.setTo(itemState), updated.setTo(t))
).update.run
} yield n