Update low balance reminder for new deposit regime
[bpt/portal.git] / remind / remind.sml
CommitLineData
dda99898
AC
1structure Remind :> REMIND =
2struct
3
4open Config
5
6structure C = PgClient
7
878a4e49
AC
8fun printReal n =
9 if n < 0.0 then
10 "-" ^ Real.fmt (StringCvt.FIX (SOME 2)) (~n)
11 else
12 Real.fmt (StringCvt.FIX (SOME 2)) n
13
dda99898
AC
14fun main _ =
15 let
16 val db = C.conn dbstring
17
878a4e49
AC
18 val totalShares = case C.oneRow db "SELECT SUM(shares) FROM WebUserPaying" of
19 [total] => C.intFromSql total
20 | _ => raise Fail "Bad SUM(shares) row"
21
22 fun doOne [user, members, shares, amount] =
23 let
24 val user = C.stringFromSql user
25 val members = C.intFromSql members
26 val shares = C.intFromSql shares
27 val amount = C.realFromSql amount
28
bb40c5c6
AC
29 val perMonth = 900.0 * real shares / real totalShares
30 val deposit = perMonth * 3.0
31 val headsUp = perMonth * 5.0
878a4e49 32 in
bb40c5c6 33 if amount >= headsUp then
878a4e49
AC
34 ()
35 else
36 let
37 val m = Mail.mopen ()
38 fun write msg = Mail.mwrite (m, msg)
39 in
bb40c5c6 40 if amount < deposit then
878a4e49
AC
41 write "Subject: Your NEGATIVE HCoop balance\n"
42 else
43 write "Subject: Your low HCoop balance\n";
44 write "From: HCoop Payment Reminder Robot <payment";
45 write emailSuffix;
46 write ">\n";
47 write "To: ";
48 write user;
49 write emailSuffix;
50 write "\nCc: payment@hcoop.net";
51 write "\n\n";
52
bb40c5c6 53 if amount < deposit then
878a4e49 54 (write "Your HCoop balance is negative. This means that you've paid less than you've\n";
bb40c5c6
AC
55 write "been charged to date, excluding your required deposit. If your account hasn't\n";
56 write "been frozen yet, expect that to happen very soon. Our bylaws allow our board\n";
57 write "of directors to vote you out of the co-op, without any obligation to contact\n";
58 write "you first, when your balance stays negative for three months. Please make a\n";
59 write "payment as soon as possible, so that we don't need to do this!\n\n")
878a4e49 60 else
bb40c5c6
AC
61 (write "With our current dues projections, you have less than two months left until\n";
62 write "your HCoop balance becomes negative, based on your sliding scale pledge amount.\n";
63 write "Please make a payment as soon as you can. We will freeze your account if your\n";
64 write "balance does become negative, and the board of directors will probably vote you\n";
65 write "out of the cooperative shortly thereafter if you don't make a payment.\n\n");
878a4e49
AC
66
67 write "Your balance: US$";
bb40c5c6 68 write (printReal (amount - deposit));
878a4e49
AC
69 write "\nTotal number of members linked to your balance: ";
70 write (Int.toString members);
71 write "\nTotal pledge amount: ";
72 write (Int.toString shares);
bb40c5c6
AC
73 write "\nDeposit: US$";
74 write (printReal deposit);
75 write "\nMinimum amount to pay to not see this message again for two months: US$";
76 write (printReal (headsUp - amount));
dda99898 77
bb40c5c6
AC
78 write "\n\nYour deposit requirement was calculated by dividing our total monthly expenses\n";
79 write "($900) by the sum of all members' pledge amounts, multiplying by your pledge amount,\n";
80 write "and then multiplying by 3. That is, the amount covers your share of three months'\n";
81 write "expenses.\n\n";
dda99898 82
878a4e49 83 write "To make a payment, visit:\n";
4763cfb8 84 write " https://members.hcoop.net/\n";
878a4e49 85 write "and use the PayPal or Google Checkout link.\n";
9a4c122a 86
9a4c122a
AC
87 write "\nIf for whatever reason you don't plan to pay the amount suggested in this e-mail,\n";
88 write "_please_ don't stay silent. Reply to this message explaining your circumstances.\n";
89 write "We are doing limited-time monetary grants on request, due to the extra costs\n";
90 write "associated with setting up our new servers.\n";
91
878a4e49
AC
92 ignore (Mail.mclose m)
93 end
94 end
95 | doOne _ = raise Fail "Bad SQL row"
dda99898 96 in
878a4e49 97 C.app db doOne "SELECT Balance.name, COUNT(*), SUM(WebUserPaying.shares) AS shrs, Balance.amount FROM WebUserPaying JOIN Balance ON WebUserPaying.bal = Balance.id GROUP BY Balance.name, Balance.amount HAVING amount < 10";
dda99898
AC
98 C.close db;
99 OS.Process.success
878a4e49
AC
100 end handle C.Sql s => (print ("SQL failure: " ^ s ^ "\n");
101 OS.Process.failure)
dda99898
AC
102
103end