Rails: How to sum total price per day - ruby-on-rails

I want to calculate total price of ticket sales on the day it sold.
But it shows total price of the last day (Today's total price).
What i got now :
October 20
Ticket 1 USD 1.11
Ticket 2 USD 2.22
Ticket 3 USD 3.33
Total For Today
USD 7.77 (HERE'S THE PROBLEM)
-------------------------------
October 21
Ticket 1 USD 1.11
Ticket 2 USD 2.22
Ticket 3 USD 4.44
Today's total
USD 7.77
What i exactly want is :
October 20
Ticket 1 USD 1.11
Ticket 2 USD 2.22
Ticket 3 USD 3.33
Today's total
USD 6.66
-------------------------------
October 21
Ticket 1 USD 1.11
Ticket 2 USD 2.22
Ticket 3 USD 4.44
Total For Today USD 7.77
What i want is how to calculate total price of each day (total price on the day those tickets has been sold)?
In ticket model
scope :daily_total_price, ->(date_time = Time.now) { where('created_at BETWEEN ? AND ?',date_time.beginning_of_day, date_time.end_of_day).sum(:price) }
In Ticket controller
def index
#tickets = Ticket.all.order("created_at DESC")
#users = User.all
end
In Ticket index
<% tickets.each do |ticket| %>
<%= ticket.created_at.strftime("%d %B") %>
<%= ticket.user.username %>
<%= ticket.price %>
<% end %>
<%= Ticket.daily_total_price) %>
Thank for helping :)

So to do what you want, I'd imagine the following code...
<% date_for_group = nil %>
<% #tickets.each do |ticket| %>
<% if ticket.created_at.to_date != date_for_group %>
<%# show total of previous group %>
<% if date_for_group %>
<br/>
Total for <%=date_for_group.strftime("%d %B") %></br>
<%= Ticket.daily_total_price(date_for_group) %>
<br/>
<% end %>
<%= ticket.created_at.strftime("%d %B") %>
<br/>
<% date_for_group = ticket.created_at.to_date %>
<% end %>
<%= ticket.user.username %>
<%= ticket.price %>
<% end %>
<% if date_for_group %>
<br/>
Total for <%=date_for_group.strftime("%d %B") %></br>
<%= Ticket.daily_total_price(date_for_group) %>
<br/>
<% end %>

You're doing
<%= Ticket.daily_total_price %>
But that always defaults the first argument to today's date (you wrote ->(date_time = Time.now) What you want to do is to pass the appropriate date in... put the date into a '#date' instance variable in your controller and then do...
<%= Ticket.daily_total_price(#date) %>

Related

Time Difference of One Item, Two Fields, Grouped by Days - Rails

Controller
#clock_events = ClockEvent.where(user_id: current_user.id)
#clock_event_days = #clock_events.group_by { |t| t.clock_in.beginning_of_day }
#clock_out = ClockEvent.where(user_id: current_user.id, clock_out: nil).last
View
<% if #clock_events.exists? %>
<div class="row">
<% #clock_event_days.each do |day, clock_events| %>
<div class="col-md-6">
<div class="list-group">
<h4 class="list-group-item-heading"><%= day.strftime("%A, %B #{day.day.ordinalize}") %></h4>
<% clock_events.each do |clock_event| %>
<p class="list-group-item-text time-group">
<%= clock_event.clock_in.strftime("%l:%M%p") %>
<% if clock_event.clock_out.present? %>
-
<%= clock_event.clock_out.strftime("%l:%M%p") %> -
<%= sprintf "%.2f", ((clock_event.clock_out - clock_event.clock_in) / 1.hour) %> hrs
<% end %>
</p>
<% end %>
</div>
<div class="daily-total">
<strong>Total: **need total here**</strong><br>
</div>
</div>
<% end %>
</div>
<% end %>
Result
Friday, February 17th
5:15PM - 6:15PM - 1.00 hrs
5:29PM - 5:41PM - 0.21 hrs
5:49PM - 6:45PM - 0.94 hrs
6:49PM - 6:49PM - 0.00 hrs
6:50PM - 6:57PM - 0.11 hrs
Total:
Saturday, February 18th
4:45PM - 4:52PM - 0.11 hrs
Total:
Can some one help me get the total hours for each day and then for the entire week (Friday-Thursday)?
I am guessing I should be using the model for getting the time difference instead of using the view...but I can't seem to figure it out.
Putting a variable to track this in the view is the most straightforward solution, even if it's maybe not the most elegant one.
<% total_hours = 0 %>
<% clock_events.each do |clock_event| %>
<% total_hours += (clock_event.clock_out - clock_event.clock_in) %>
<% end %>
and then output it
<strong>Total: <%= total_hours / 1.hour %></strong><br>
Edit 1:
You could also clean things up a bit by adding this in the model, something like
class ClockEvent < ApplicationRecord
# ..
def duration
clock_out - clock_in
end
end
and use that in the view
<% total_hours += clock_event.duration %>
...
<%= sprintf "%.2f hrs", (clock_event.duration / 1.hour) %>
Edit 2:
You can clean it up even more by skipping the total_hours variable all together and do this.
<%= clock_events.sum(&:duration) / 1.hour %>

How to sort group_by month and year in view?

pages_controller.rb
#past_challenges_by_years = #past_challenges.group_by { |t| [t.deadline.year, t.deadline.month] }
How can I break it down in the view with year and then subdivide it with month like this:
2014 # Years
01 # Months
Challenge
Challenge
02
Challenge
08
Challenge
2016
03
Challenge
08
Challenge
view.html.erb
<% #past_challenges_by_years.sort.each do |year, challenges| %>
<%= year %>
<%= month %> # I don't know how to define this.
<% for challenge in challenges %>
etc...
<% end %>
<% end %>
I would start by sorting the keys and then look up the challenges while iterating through those keys.
<% #past_challenges_by_years.keys.sort.each do |(year, month)| %>
<%= year %>
<br />
<%= month %>
<br />
<% #past_challenges_by_years[[year, month]].each do |challenge| %>
<%= challenge %>
<br />
Edit: Here is a new solution that only displays years and months once.
#past_challenges_by_years.keys.map { |a| a[0] }.uniq.sort.each do |year|
puts year
#past_challenges_by_years.keys.select { |a| a[0] == year }.map { |a| a[1] }.uniq.sort.each do |month|
puts month
#past_challenges_by_years[[year, month]].each do |challenge|
puts challenge
end
end
end
I think it should be simple enough to convert to ERB.

How to render only notes that equal date?

Instead of showing all the notes per day, how can we only show one note per day, the note whose note.note_date == date?
Day 1: Notes/notes # Shows both Day 1 and Day 3 note. Only want to show Day 1 note
Day 2: Notes/form
Day 3: Notes/notes # Shows both Day 1 and Day 3 note. Only want to show Day 3 note
Day 4: Notes/form
Day 5: Notes/form
challenges/show
<% #challenge.dates_challenged.first(#challenge.days_challenged).each_with_index do |date, i| %>
Day <%= i + 1 %>
<% if #notes.any? { |note| note.notes_date.strftime("%m/%d/%y") == date.strftime("%m/%d/%y") } %>
<%= render 'notes/notes' %>
<% else %>
<%= render 'notes/form', :date => date %>
<% end %>
<% end %>
notes/notes
<% #notes.each do |note| %>
<%= note.notes_text %>
<% end %>
notes/form
<%= form_for [#notable, #note] do |f| %>
<%= f.text_area :notes_text, placeholder: 'Enter Recap' %>
<%= f.date_select :notes_date, selected: date, :order => [:month, :day, :year] %>
<% end %>
challenges_controller
def show
#notable = #challenge
#notes = #notable.notes
#note = Note.new
end
To recap, a user creates a challenge. A challenge has the attribute days_challenged. The user chooses how many days will be challenged, i.e. 10, 15, 30, etc. For each of those days a notes/form will be rendered. If a note.notes_date equals a respective day then how can we only show that one note in place of notes/form?
<% if #notes.any?
#today_notes = #notes.select{ |note| note.notes_date.strftime("%m/%d/%y") == date.strftime("%m/%d/%y") } %>
<%= render 'notes/notes' %>
<% else %>
...
<% end %>
Then use #today_notes in the notes/notes partial.
Change this <%= render 'notes/notes' %> partial to below one, and follow right below note.html.erb file.
Challenges Show:
<%= render partial: 'notes/notes', locals:{note: note} %>
Rename note.html.erb to underscore _notes.html.erb
notes/_notes.html.erb:
<%= note.notes_text %>

Having trouble parsing and spacing date/fixnum objects

I'm building a small app that takes things entered into an input field and displays them directly below that input field when entered.
My goal with this code is to separate those entries by date so that all things posted on June 1 are posted with one line break between them and the first entry of June 2 has 2 spaces between it and the entries from June 1.
This is my code and it's not acting as planned but I can't figure out why, I think it stems from line 3 and something I'm doing incorrectly. (Note: I'm aware this doesn't account for changes in month or year yet. I'll get to that once I figure out proper date spacing)
<% for i in (0..(#allLessons.count-1)) %>
<b><%= #date[i].created_at.strftime('%b %d')%></b><br/>
<% if #date[i].created_at.strftime('%d') == #date[i-1].created_at.strftime('%d') %>
<%= #date[i].created_at.strftime('%d') %> <br />
<% else %>
<%= #date[i].created_at.strftime('%d') %><br /><br />
<% end %>
<% end %>
From the controller:
#allLessons = Lesson.all
#date = Lesson.find(:all, :order => 'created_at ASC')
Any help you could lend on this would be hugely appreciated!
Blocks and iterators are where it's at.
#allLessons = Lesson.order('created_at ASC')
#dates = #allLessons.group_by { |lesson| lesson.created_at.beginning_of_day }.sort
<% #dates.each do |date, lessons| %>
<% lessons.each do |lesson| %>
<b><%= lesson.created_at.strftime("%d") %></b><br />
<% end %>
<br />
<% end %>
Annotated
First we get all of the lessons together. This is equivilant to find(:all, :order => 'created_at ASC'), but I like this newer, compact syntax
#allLessons = Lesson.order('created_at ASC')
Then we group them all together into a hash where the key is the date and the value is an array of records that were created on that day. beginning_of_day converts a DateTime into a Date where the time is set to 00:00:00. So, 2012-05-25 18:00 becomes 2012-05-25 00:00:00. This is so we can group the dates themselves without the time getting in the way
#dates = #allLessons.group_by { |lesson| lesson.created_at.beginning_of_day }.sort
#dates is now a hash where the keys are dates and the values are arrays of lessons from that date. for example, { '2012-05-24 00:00:00' => [ lesson_1 ], 2012-05-25 00:00:00' => [ lesson_2, lesson_3 ]
We then pass the hash into a block, where the key is the date, and the value is the array of lessons. This is saying, for each date...
<% #dates.each do |date, lessons| %>
Give me the lessons that belong to that date. And for each of those...
<% lessons.each do |lesson| %>
print out the date of the lesson
<b><%= lesson.created_at.strftime("%d") %></b><br />
<% end %>
before moving on to the next date, print a <br />
<br />
<% end %>

Rails hash and arrays

I am making a timesheet, but i have problems.
I want it to look like this:
projects |Monday Tuesday Wednesday Thursday Friday Saturday Sunday
development| 3:50 4:00 5:00 3:00 0:00 0:00 0:00
Testing | 0:00 0:00 0:00 2:00 4:00 0:00 0:00
Lanch | 0:00 0:00 0:00 0:00 1:00 6:00 0:00
Every project has_many logs with hours as a field.
I did this query:
#log_week_project = current_user.logs.where(:log_date => (Time.now.beginning_of_week + 1.second)..(Time.now.end_of_week - 1.second)).group("project_id").group("date(log_date)").sum(:hours)
And get this:
<OrderedHash {[2, "2011-05-24"]=>31800.0, [1, "2011-05-24"]=>10200.0, [1, "2011-05-23"]=>25200.0, [1, "2011-05-26"]=>19800.0}>
The key in the hash is an array with the project_id # [0] and log_date # [1]. The value is the hours.
I do this in my view:
<% for project in #projects do %>
<%= project.name %>
<% #log_week_project.map do |key,hours|%>
<% if key[0] == project.id %>
<%= time_diff(hours)%>
<% end %>
<% end %>
<% end %>
This gives me the project hours on each date, but if there is a date with no hours there is no output and the table gets wrong.
If there is no hours on wednesday the thursday hours ends up in the wednesday column.
Any tips on how to do this? Perhaps there is a better way?
SOLUTION:
Thanks for replies and comments. The solution was:
<% for project in #projects do %>
<%= project.name %>
<% #dates.each do |date| %>
<% hours = #log_week_project.detect { |key| key[0][0].to_i == project.id && key[0][1].to_time.strftime('%a') == date.to_time.strftime('%a')}%>
<%= hours ? time_diff(hours[1]) : "0:00"%>
<% end %>
<% end %>
Where #dates is an array of the dates in the timerange. Now refactoring... ; )
you can do this:
<% for project in #projects do %>
<%= project.name %>
<% (1..7).each do |day| %>
<% date = "2011-05-#{22 + day}" #please modify this, this is only to keep the example simple %>
<% hours = #log_week_project.detect{|key| key[0] == project && key[1] == date } %>
"<%= hours ? time_diff(hours) : "" %>
<% end %>
<% end %>
<% end %>
<% end %>
next, refactor this to put all the logic in a helper.
Hope, that helps
In your database you may have 0 as default for all hours, that way it can't be blank.
But if you storing hours in logs, then you can't do above. In that case, use
time_diff(hours).present? ? time_diff(hours) : 0
Or else you may use anything else than 0, that way tables will not disturbed.

Resources