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