1# frozen_string_literal: true
2
3require_relative "./usage_report"
4
5class CustomerUsage
6 def initialize(customer_id)
7 @customer_id = customer_id
8 end
9
10 def usage_report(range)
11 EMPromise.all([
12 messages_by_day(range),
13 minutes_by_day(range)
14 ]).then do |args|
15 UsageReport.new(range, *args)
16 end
17 end
18
19 def expire_message_usage
20 today = Time.now.utc.to_date
21 REDIS.zremrangebylex(
22 "jmp_customer_outbound_messages-#{@customer_id}",
23 "-",
24 # Store message counts per day for 1 year
25 "[#{(today << 12).strftime('%Y%m%d')}"
26 )
27 end
28
29 def incr_message_usage(amount=1)
30 today = Time.now.utc.to_date
31 EMPromise.all([
32 expire_message_usage,
33 REDIS.zincrby(
34 "jmp_customer_outbound_messages-#{@customer_id}",
35 amount,
36 today.strftime("%Y%m%d")
37 )
38 ])
39 end
40
41 def message_usage(range)
42 messages_by_day(range).then do |by_day|
43 by_day.values.sum
44 end
45 end
46
47 def messages_by_day(range)
48 EMPromise.all(range.first.downto(range.last).map { |day|
49 REDIS.zscore(
50 "jmp_customer_outbound_messages-#{@customer_id}",
51 day.strftime("%Y%m%d")
52 ).then { |c| [day, c.to_i] if c }
53 }).then { |r| r.compact.to_h.tap { |h| h.default = 0 } }
54 end
55
56 QUERY_FOR_MINUTES = <<~SQL
57 SELECT
58 date_trunc('day', start)::date as day,
59 CEIL(SUM(billsec)/60.0)::integer as minutes
60 FROM cdr
61 WHERE customer_id=$1 and start >= $3 and date_trunc('day', start) <= $2
62 GROUP BY date_trunc('day', start);
63 SQL
64
65 def minutes_by_day(range)
66 DB.query_defer(
67 QUERY_FOR_MINUTES,
68 [@customer_id, range.first, range.last]
69 ).then do |result|
70 result.each_with_object(Hash.new(0)) do |row, minutes|
71 minutes[row["day"]] = row["minutes"]
72 end
73 end
74 end
75
76 def calling_charges_this_month
77 DB.query_one(<<~SQL, @customer_id).then { |r| r[:charges] }
78 SELECT COALESCE(SUM(charge), 0) AS charges
79 FROM cdr_with_charge
80 WHERE customer_id=$1 AND start >= DATE_TRUNC('month', LOCALTIMESTAMP)
81 SQL
82 end
83end