process_invite_rewards

 1#!/usr/bin/ruby
 2# frozen_string_literal: true
 3
 4require "bigdecimal"
 5require "dhall"
 6require "pg"
 7
 8PLANS =
 9	Dhall::Coder
10	.new(safe: Dhall::Coder::JSON_LIKE + [Symbol])
11	.load(<<-DHALL, transform_keys: ->(k) { k&.to_sym })
12		let Quota = < unlimited | limited: { included: Natural, price: Natural } >
13		let Currency = < CAD | USD >
14		in
15		(#{ARGV[0]}) : List {
16			name: Text,
17			currency: Currency,
18			monthly_price: Natural,
19			minutes: Quota,
20			messages: Quota,
21			allow_register: Bool,
22			subaccount_discount: Natural
23		}
24DHALL
25
26db = PG.connect(dbname: "jmp")
27db.type_map_for_results = PG::BasicTypeMapForResults.new(db)
28db.type_map_for_queries = PG::BasicTypeMapForQueries.new(db)
29
30QUERY = <<~SQL
31	SELECT code::TEXT, creator_id, plan_name
32	FROM
33		invites
34		INNER JOIN transactions ON used_by_id = transactions.customer_id
35		INNER JOIN customer_plans ON creator_id = customer_plans.customer_id
36	WHERE rewarded_at IS NULL AND used_by_id IS NOT NULL AND amount > 0
37	GROUP BY used_by_id, code, creator_id, plan_name
38	HAVING
39		MIN(transactions.settled_after) < LOCALTIMESTAMP - '2 days'::interval
40		AND
41		SUM(transactions.amount) >= 15
42SQL
43
44db.transaction do
45	db.exec(QUERY).each do |row|
46		puts row["code"]
47		plan = PLANS.find { |p| p[:name] == row["plan_name"] }
48		price = BigDecimal(plan[:monthly_price]) / 10000
49		db.exec(<<~SQL, [row["creator_id"], row["code"], price])
50			INSERT INTO transactions
51				(customer_id, transaction_id, settled_after, amount, note)
52			VALUES
53				($1, 'reward_' || $1 || '_for_' || $2, LOCALTIMESTAMP, $3, 'Reward for referral ' || $2)
54		SQL
55		db.exec(<<~SQL, [row["creator_id"]])
56			INSERT INTO invites (creator_id) VALUES ($1)
57		SQL
58		db.exec(<<~SQL, [row["code"]])
59			UPDATE invites
60			SET rewarded_at=LOCALTIMESTAMP
61			WHERE code=$1
62		SQL
63	end
64end