Calculate overdue tasks based on their status

I have a resource Task

I need to calculate overdue tasks based on their status: in_progres and due_date: less than current date.

defmodule Ash.Task do
  use Ash.Resource,
    otp_app: :ash,
    domain: Ash.Assignments,
    data_layer: AshPostgres.DataLayer

  postgres do
    table "tasks"
    repo Ash.Repo
  end

  actions do
    default_accept [:title, :description, :due_date, :status, :story_point]
    defaults [:create, :read, :update, :destroy]
  end

  attributes do
    uuid_primary_key :id

    attribute :title, :string
    attribute :description, :string
    attribute :status, :atom, public?: true, constraints: [one_of: [:todo, :in_progress, :done]]
    attribute :due_date, :utc_datetime, public?: true
    attribute :story_point, :integer
    timestamps()
  end
end

Ash.Task
|> Ash.Query.calculate(:overdue_tasks, :integer, filter: [status: :in_progress, due_date: [less_than: DateTime.utc_now])
|> Ash.read!()

How to write correct filter exp for query calculate?

I would define a read action:

read :overdue do
    filter expr(status == :in_progress and due_date < ^now())
end

And then use that read action with Ash.count().

If I understand Ash correctly calculations and aggregates are based on single instances of a record, not over the whole dataset. You could also calculate how many overdue tickets there are for every todo on every todo using a calculation. An example of that is in the docs even.

However, for your case a read action makes more sense I think.

2 Likes

@FlyingNoodle Thanks, I got the solution.

1 Like