Skip to content

Instantly share code, notes, and snippets.

@baldwindavid
Last active January 15, 2021 19:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save baldwindavid/78dd8ca6af95cb81da66449d4e42a78a to your computer and use it in GitHub Desktop.
Save baldwindavid/78dd8ca6af95cb81da66449d4e42a78a to your computer and use it in GitHub Desktop.
unit_statuses =
# There is a Unit schema that is tied to a "units" table
from(unit in Unit,
# grab a lease tied to a unit (office space)
# Leases have start and end dates so the lease must be during the week
# of the given `date`. This will scope leases to that requirement.
left_join: lease in ^Leasing.filter_active_leases_during_week(Lease, date),
on: lease.unit_id == unit.id,
# join the unit type (Salon, Office, Focus, etc)
join: unit_type in assoc(unit, :unit_type),
# select only these two pieces of data
# The lease.id will either be an ID or nil
select: %{unit_type_name: unit_type.name, lease_id: lease.id}
)
# Only query for units for the given property
|> Inventory.filter_units_by_property(property)
# Up until this point the query is just being built; the database hasn't
# been queried yet. Repo.all() will query the database and return a List
# in the form...
# [
# %{unit_type_name: "Salon", lease_id: xxx},
# %{unit_type_name: "Salon", lease_id: nil},
# %{unit_type_name: "Focus", lease_id: xxx}, ...
|> Repo.all()
# Group the data by unit type name returning...
# %{
# "Salon" => [%{unit_type_name: "Salon", lease_id: xxx},...],
# "Focus" => [...], ...
# }
|> Enum.group_by(& &1.unit_type_name)
# Iterate through each of those maps and gather each with into a new
# list with maps containing calculated values for each unit type...
#
# [
# %{
# unit_type_name: "Salon",
# total_count: 25,
# occupied_count: 20,
# vacant_count: 5,
# percent_occupied: 80%
# }
# ...
# ]
#
# Note that fn {unit_type_name, unit_statuses} -> works here because
# you're dealing with key value pairs which can be patterned match in the
# form of a tuple {key, value}
|> Enum.map(fn {unit_type_name, unit_statuses} ->
# Enum.count just counts a collection
total_count = Enum.count(unit_statuses)
# Enum.count optionally takes a function to filter out only matching
# values. & &1.lease_id is a shorthand for an anonymous function. This is the same
# as... Enum.count(unit_statuses, fn status -> status.lease_id end)
occupied_count = Enum.count(unit_statuses, & &1.lease_id)
# The same shorthand is used here except with a named function `is_nil`
# and passing it the argument of &1.lease_id. Supposing I wanted to call
# `is_nil` with a value rather than a struct, it could be called as
# `&is_nil/1` and the value would just automatically passed as the
# argument.
vacant_count = Enum.count(unit_statuses, &is_nil(&1.lease_id))
percent_occupied =
Number.Percentage.number_to_percentage(occupied_count / total_count * 100, precision: 0)
# Just returning a dumb map
# The result of all this will be a list of these maps.
%{
unit_type_name: unit_type_name,
total_count: total_count,
occupied_count: occupied_count,
vacant_count: vacant_count,
percent_occupied: percent_occupied
}
end)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment