Allocate daily sales to date created - ruby-on-rails

Im trying to gather all sales made within a week and put each sale in day made. If Moday was two sales, then Monday => {...}, {...} etc
"Monday" would be ruby's date format.
In my db I have 5 sale objects: Two sales on Monday and two on Tuesday.
Controller:
def daily_customer_sale(created)
date_and_id = Sale.where('created_at >= ?', created).pluck(:created_at, :id)
date_and_id.each do |obj|
yield(obj.first, obj.last)
end
end
def daily_sales(created=nil)
sales_by_date = Hash.new(0)
daily_customer_sale(created) do |date, id|
s_date = date.to_date
sales_by_date[s_date] = Sale.find(id) # Seems to return only one object per day
end
return sales_by_date
end
For views:
daily_sales(1.week.ago.to_datetime)
What I get in two dates (correct) in which each data has only one object when it should be two or more per date. Is there something wrong?

You don't need complex logic to do it. Here is a cleaner way
Sale.where('created_at >= ?', created_at).group_by{ |sale| sale.created_at.to_date}
It will return All the sales grouped by day.
key will be date object and for each day there will be sale array containing all of the sales for that day.
If you need string based key you can format it as you like as per below
Sale.where('created_at >= ?', created_at).group_by{ |sale| sale.created_at.to_date.to_s } #default date format
Sale.where('created_at >= ?', created_at).group_by{ |sale| sale.created_at.to_date.strftime("%d/%m/%Y") } #23/09/2016
You can have a look at Group by method

Related

How to get weekly records on Rails?

I have Payment model with data and amount attributes. Now I need to get all the records for the current week on the page. I want to use some kind of pagination, e.g.: On the first page I get all records for the current week, on the second page - records from the previous week etc.
And on every page I need to get total amount for this week and average amount per day.
So, I have two questions:
How to get all the records for particular week on the page?
How to count amount for this week?
Now everything I've done was array with weeks and amounts
def self.count_by_week
raw_result = group_by_week_and_state.count
# {['2014-12-01-2014-12-07', 'foo'] => 100, ['2014-12-01-2014-12-07', 'bar'] => 100, '...' => '...'}
raw_result.each_with_object({}) do |(k, v), result|
result[k[0]] ||= {}
result[k[0]][k[1]] = v
end
end
def self.group_by_week_and_state
group("#{weekday_query(0)} || \'-\' || #{weekday_query(6)}").group('amount')
end
# build sql part for day offset of week (0 => mon, 6 => sun)
def self.weekday_query(offset)
"to_char(cast(date_trunc(\'week\', created_at) as date) + #{offset}, \'YYYY-MM-DD\')"
end
You could use the groupdate gem to accomplish this.
https://github.com/ankane/groupdate
Once you have successfully grouped your records, it's just too simple to get the sum for each groups.

Display all the records when due date is less than current date in Rails

I am having a Quote model which consists of due_date and other fields.
I need to write a condition where we have to display all the records where due_date (which is date data type and stored in database as yyyy-mm-dd format) is less than current date.
For example, current_date is today's date, so I need to display all the records till yesterday.
I wrote a condition but didn't work, can you tell me where I went wrong?
def past_quotes
#items = []
current_date = Time.now.strftime("%Y-%m-%d")
daily_items = Quote.by_account(#account).active.includes(:company).where('due_date' < current_date)
#items << Item.new(items: daily_items) unless daily_items.empty?
end
But still displaying all the records, I think condition is wrong.
You shouldn't use a string when comparing the dates. ActiveRecord should be able to handle dates directly
daily_items = Quote.by_account(#account).active.includes(:company).where('due_date < ?', Date.today)
Can you try following query:
def past_quotes
#items = []
daily_items = Quote.by_account(#account).active.includes(:company).where('due_date < DATE(?)', Time.now)
#items << Item.new(items: daily_items) unless daily_items.empty?
end

Repeat records based on date - Rails

I have a table of events that have start and end dates.
Now I want to fetch events for particular dates. i.e if I supply 1 May 2014, 2 May 2004, I need all events happening on that day (based on start and end dates). And I need to group the events based on the start date and display them as a list.
Now problem is if an event takes place on two days, say 1 May and 2 May, I need to display the event twice in the list like so:
1 May 2014
EventName
2 May 2014
EventName
I am not sure how to do this... Can anyone help me come up with an efficient way to do this?
To get the events to appear twice I would add separately created collections together.
events = []
(start_date..end_date).each do |date|
events += Event.where("start_date >= ? and end_date <= ?", date, date)
end
events
events = Event.where("start_date >= ? AND end_date <= ?", start_date, end_date)
display_events = Hash.new
(start_date..end_date).each do |date|
display_events[date] << events.select { |event| event.start_date <= date and event.end_date >= date }
end
Here you end up having a hash with events grouped by date. (I'm on cellphone, so I couldn't test it)
Try to fetch and display all events on each day.i.e iterate data not on the basis on event rather iterate on the basis of event dates.
s_date = Date.parse('2010-09-29')
e_date = Date.parse('2010-09-30')
sd.upto(ed) do |date|
#events = Event.event_on_date(date)
end

How do I find the sum of donations per month for 24 months?

Having pulled donations from the past two years, I'm trying to derive the sum of those donations per month (a total of 24 sums), storing the keys (each month) and the values (the sum of donations for each month) in an array of hashes.
Here's what I've got so far:
#donations = Gift.between(Date.today - 2.years, Date.today, :field => gift_date)
#donations.each do |donation|
#logic here that puts gift_amount into the right month (of the 24 months)
# and adds it to the previous balance for that month, ending up with 24 keys
# and sum values.
end
How can I do this in Ruby/Rails?
Continuing where #mbratch left off:
donations = Gift.where(:date => (Date.today - 2.years)..Date.today)
Hash[donations.group_by { |d| [d.date.year, d.date.month] }
.map do |year_month, donations|
[year_month, donations.map(&:amount).reduce(:+)]
end]
donation_hash = Hash.new(0)
Gift.where(:gift_date => (Date.today - 2.years)..Date.today).each do |donation|
donation_hash[[donation.gift_date.month, donation.gift_date.year]] += donation.amount
end
This will create a hash with keys of [month, year] and value of total amount donated for that month/year. There are probably a few other suitable ways to create a key which meets the need of your application.

Output array based on date (sales figures by day)

I have a table with a float called 'cost' and timestamp called'created_at'.
I would like it to output an array with the summing the costs for each particular day in the last month.
Something like:
#newarray = [] #creating the new array
month = Date.today.month # Current Month
year = Date.today.year # Current Year
counter = 1 # First Day of month
31.times do #for each day of the month (max 31)
#adding sales figures for that day
#newarray.push(Order.sum(:cost, :conditions => {:created_at => "#{year}-#{month}-#{counter}"}))
counter = counter + 1 #go onto next day
end
However this doesn't work as all the timestamps have a time as well.
Apologies in advance for the poor title, I can't seem to think of a sensible one.
You should be able to use code like the following:
sales_by_day = Order.sum(:cost,
:group => 'DATE(created_at)',
:conditions => ['DATE(created_at) > ?', 31.days.ago])
(0..30).collect { |d| sales_by_day[d.days.ago.to_date.to_s] || 0 }.reverse
This will sum the order cost by day, then create an array with index 0 being the last 24 hours. It will also take only one query, whereas your example would take 31.
To change the cut off date, replace 31.days.ago with an instance of the Time class. Documentation here: http://ruby-doc.org/core/classes/Time.html
Good luck!
This should work:
(Date.today.beginning_of_month..Date.today.end_of_month).map { |d|
Order.sum(:cost, :conditions => ['created_at >= ? AND created_at < ?', d, d+1])
}
Although I think you should try getting it using a single query, instead of making one for each day.

Resources