Skip to content

Commit

Permalink
Add "cost of doing epic" page. So far it gathers and processes the da…
Browse files Browse the repository at this point in the history
…ta, but doesn't do any nice presentation. Part of #30
  • Loading branch information
Adrian McEwen committed Jan 8, 2025
1 parent e0062c2 commit 93a56aa
Show file tree
Hide file tree
Showing 4 changed files with 200 additions and 0 deletions.
102 changes: 102 additions & 0 deletions app/controllers/reports_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -170,4 +170,106 @@ def income_distribution
@categories = @totals.keys
@periods = periods_hash.keys.sort
end

def cost_of_doing_epic
@title = "Cost of Doing Epic"

categories_hash = {}
exclusions = params[:exclusions] || []
ProductCategoryDescription.all.each do |pcd|
category = pcd.product_category.name
categories_hash[pcd.description] = category
end

begin
@start_date = Date.parse(params[:start_date])
rescue Exception
@start_date = Invoice.minimum(:date)
end
begin
@end_date = Date.parse(params[:end_date])
rescue Exception
@end_date = Date.today
end
@six_month_start_date = Date.today.prev_month.beginning_of_month.months_ago(5)
@six_month_end_date = Date.today.prev_month.end_of_month

@income_split = {}
@incomings = {}
@outgoings = {}
InvoiceItem.joins(:invoice).where(["`date` >= ? AND `date` < ?", @start_date, @end_date]).each do |item|
category_name = categories_hash[item.description]
if exclusions.include?(category_name)
next
end
if item.subtotal < 0
puts "Skipping "+item.inspect
next
end
puts "Unknown category: #{item.description} #{item.subtotal}"
if category_name.nil?
category_name = "Uncategorized"
end
if @income_split[category_name].nil?
@income_split[category_name] = 0.0
end
@income_split[category_name] += Float(item.subtotal)
end

# Find and categorise the expenses
BankAccountEntry.where(["`date` >= ? AND `date` < ?", @start_date, @end_date]).each do |item|
if item.entry_type.match?("Transfer.*Another Account")
next
end
if Float(item.gross_value) > 0
# Money in!
if @incomings[item.entry_type].nil?
@incomings[item.entry_type] = 0
end
puts item.inspect
@incomings[item.entry_type] += Float(item.gross_value)
else
if @outgoings[item.entry_type].nil?
@outgoings[item.entry_type] = 0
end
puts item.inspect
@outgoings[item.entry_type] += -1*Float(item.gross_value)
end
end

# Summarize and...
@total_incoming = @incomings.values.sum
@total_outgoing = @outgoings.values.sum
# ...roll the smaller items into an "other" category
other_incoming, wanted_incoming = @incomings.partition { |k, v| v < 100.00 } #@total_incoming/50 }
@incomings = wanted_incoming.to_h
@incomings["Other"] = other_incoming.to_h.values.sum unless other_incoming.empty?
other_outgoing, wanted_outgoing = @outgoings.partition { |k, v| v < 100.00 } #@total_outgoing/50 }
@outgoings = wanted_outgoing.to_h
@outgoings["Other"] = other_outgoing.to_h.values.sum unless other_outgoing.empty?
other_income_split, wanted_income_split = @income_split.partition { |k, v| v < @total_incoming/80 }
@income_split = wanted_income_split.to_h
@income_split["Other"] = 0
@income_split["Other"] += other_income_split.to_h.values.sum unless other_income_split.empty?
@income_split["Other"] += @income_split["Uncategorized"] unless @income_split["Uncategorized"].nil?
@income_split.delete("Uncategorized")

# Work out split of invoices based on categories in @income_split
@total_income_split = @income_split.values.sum
@processed_incomings = @income_split.transform_values do |value|
(value / @total_income_split) * @total_incoming
end
@total_processed_incoming = @processed_incomings.values.sum

# Convert them to a-month's-worth of values
one_month_multiplier = 31/(@end_date - @start_date).to_f
@monthly_incomings = @processed_incomings.transform_values { |v| v*one_month_multiplier }
@monthly_outgoings = @outgoings.transform_values { |v| v*one_month_multiplier }
@total_monthly_incoming = @monthly_incomings.values.sum
@total_monthly_outgoing = @monthly_outgoings.values.sum

# Draw a chart

@categories = @income_split.keys
end
end
1 change: 1 addition & 0 deletions app/views/layouts/application.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
<li><%= link_to "Categories", { controller: "reports", action: "categories" } %>
<li><%= link_to "Income Distribution", { controller: "reports", action: "income_distribution" } %>
<li><%= link_to "Service Users", { controller: "reports", action: "service_users" } %>
<li><%= link_to "Cost of Doing Epic", { controller: "reports", action: "cost_of_doing_epic" } %>
</ul>
<%= yield %>
</body>
Expand Down
96 changes: 96 additions & 0 deletions app/views/reports/cost_of_doing_epic.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<%= form_tag("", method: "get") do %>
<%= label_tag :start_date, "Start date:" %>
<%= text_field_tag :start_date, @start_date, size:12 %>
<%= label_tag :end_date, "End date:" %>
<%= text_field_tag :end_date, @end_date, size:12 %>
<%= label_tag :stacked_percent, "Stacked as percent:" %>
<%= check_box_tag :stacked_percent, "on", params[:stacked_percent] =='on' %>
<%= label_tag :exclusions, "Exclude categories:" %>
<%= select_tag :exclusions, options_for_select( ProductCategory.all.map { |c| c.name }, params[:exclusions]), {multiple: true, size: 5} %>
<%= submit_tag "Show" %>
<% end %>
<%= form_tag("", method: "get") do %>
<%= hidden_field_tag :start_date, @six_month_start_date %>
<%= hidden_field_tag :end_date, @six_month_end_date %>
<%= submit_tag "Last 6 Months" %>
<% end %>
<%= form_tag("", method: "get") do %>
<%= hidden_field_tag :start_date, "" %>
<%= hidden_field_tag :end_date,"" %>
<%= submit_tag "All Time" %>
<% end %>

<h3>@income_split</h3>
<ul>
<% @income_split.each do |incoming| -%>
<li><%= incoming -%></li>
<% end -%>
</ul>

<h3>@incomings</h3>
<ul>
<% @incomings.each do |incoming| -%>
<li><%= incoming -%></li>
<% end -%>
</ul>

<h3>@outgoings</h3>
<ul>
<% @outgoings.each do |outgoing| -%>
<li><%= outgoing -%></li>
<% end -%>
</ul>

<h3>@processed_incomings</h3>
<ul>
<% @processed_incomings.each do |processed| -%>
<li><%= processed -%></li>
<% end -%>
</ul>

<p>total_income_split: <%= @total_income_split -%>,
total_incoming: <%= @total_incoming -%>,
total_processed_incoming: <%= @total_processed_incoming -%></p>

<h3>@monthly_incomings - total: <%= @total_monthly_incoming -%></h3>
<ul>
<% @monthly_incomings.each do |item| -%>
<li><%= item -%></li>
<% end -%>
</ul>

<h3>@monthly_outgoings - total: <%= @total_monthly_outgoing -%></h3>
<ul>
<% @monthly_outgoings.each do |item| -%>
<li><%= item -%></li>
<% end -%>
</ul>

<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript">
google.charts.load('current', {'packages':['corechart']});
google.charts.setOnLoadCallback(function() {
drawTotalsBarChart()
});

function drawTotalsBarChart() {
var dataArray = [
];
var data = google.visualization.arrayToDataTable(dataArray);

var options = {
isStacked: <%= raw (params[:stacked_percent] == 'on' ? 'percent' : true).to_json %>
};

var chart = new google.visualization.BarChart(document.getElementById('bar_chart'));
google.visualization.events.addListener(chart, 'ready', function () {
var link = document.getElementById('bar_chart_link')
link.href = chart.getImageURI()
link.style.visibility = "visible"
});

chart.draw(data, options);
}
</script>
<div id="bar_chart" style="width: 900px; height: 500px"></div>
<a id="bar_chart_link" style="visibility: hidden;" href="">Download Chart</a>
1 change: 1 addition & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@
get "/reports/categories", to: "reports#categories"
get "/reports/income_distribution", to: "reports#income_distribution"
get "/reports/service_users", to: "reports#service_users"
get "/reports/cost_of_doing_epic", to: "reports#cost_of_doing_epic"
end

0 comments on commit 93a56aa

Please sign in to comment.