src/main/scala/fis/pm/model/Task.scala
author Tomas Zeman <tzeman@volny.cz>
Tue, 23 Apr 2013 10:36:04 +0200
changeset 108 ef4e3e0ef83f
parent 103 6a2a19785cd8
permissions -rw-r--r--
84a94fa29a67504b Task/Project notifications

/*
 * Copyright 2012 Tomas Zeman <tzeman@volny.cz>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package fis.pm.model

import fis.aaa.model._
import fis.base.model.{Entity, ReadOnlyField}
import fis.db.PgsqlSequencer
import fis.cl.model._
import net.liftweb.common._
import net.liftweb.record.{LifecycleCallbacks, MetaRecord, Record}
import net.liftweb.record.field._
import net.liftweb.squerylrecord.RecordTypeMode._
import net.liftweb.util._
import net.tz.lift.model._
import net.tz.lift.model.{FieldLabel => FL}
import org.squeryl.annotations.Column
import org.squeryl.dsl.QueryDsl
import org.squeryl.dsl.ast.LogicalBoolean
import scala.xml.Text

class Task private() extends Record[Task] with Entity[Task] {
  def meta = Task

  @Column("project_id")
  val project = new LongField(this) with ProjectField with FL
  val deadline = new JodaDateMidnightField(this) with FL
  val taskType = new OptionalCodeListItemField(this, 'task_type) with FL
  val responsible = new UserField(this, meta.users, getUserVendor) with
    DefaultCurUser with FL

  @Column("state")
  protected[pm] val stateFld = new CodeListItemField(this,
    CodeList('task_state), _.i1.toString, { v => Text(v.i1.toString)}) with FL

  @Column("num")
  protected val numFld = new TaskNumber(this)
  lazy val ident = ReadOnlyField(numFld)
  def number = (numFld.year, numFld.get)
  def numberStr = numFld.toString

  def state: TaskState =
    stateFld.item.map { TaskState(_) } openOr EmptyTaskState

  def delayed = !state.complete &&
    deadline.date.plusDays(1).isBefore(null) // null means now
}

object Task extends Task with MetaRecord[Task] with SimpleInjector {
  object users extends Inject[Iterable[User]](() => Nil)
}

abstract sealed class TaskState {
  def id: Long
  def finishedPercent: Int
  def complete: Boolean
}
case class TaskStateItem(id: Long, finishedPercent: Int, complete: Boolean)
  extends TaskState
case object EmptyTaskState extends TaskState {
  def id = 0
  def finishedPercent = 0
  def complete = false
}
object TaskState {
  def apply(i: CodeListItem): TaskState =
    TaskStateItem(i.id, i.i1.get, i.i1.get == 100)

  def unfinishedClause[T](i: CodeListItem)(implicit dsl: QueryDsl):
    LogicalBoolean = (i.i1 <> 100)
}

private[model] class TaskNumber(t: Task) extends IntField[Task](t) with
  LifecycleCallbacks with FL {

  def year = t.createdAt.dateTime.getYear
  override def beforeCreate {
    val sequencer = PgsqlSequencer("task_%d".format(year))
    set(sequencer.next.toInt)
  }
  override def toString = "%d/%03d".format(year, get)
  override def asHtml = Text(toString)
}

// vim: set ts=2 sw=2 et: