Finish changes to follow dues policy changes
[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 29 val perMonth = 900.0 * real shares / real totalShares
c8abf2d9
AC
30 val deposit = 900.0 / real totalShares * 3.0
31 val headsUp = deposit + perMonth * 2.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 78 write "\n\nYour deposit requirement was calculated by dividing our total monthly expenses\n";
c8abf2d9
AC
79 write "($900) by the sum of all members' pledge amounts and then multiplying by 3. That\n";
80 write "is, the amount covers a minimal share of three months' expenses.\n\n";
dda99898 81
878a4e49 82 write "To make a payment, visit:\n";
4763cfb8 83 write " https://members.hcoop.net/\n";
878a4e49 84 write "and use the PayPal or Google Checkout link.\n";
9a4c122a 85
9a4c122a
AC
86 write "\nIf for whatever reason you don't plan to pay the amount suggested in this e-mail,\n";
87 write "_please_ don't stay silent. Reply to this message explaining your circumstances.\n";
9a4c122a 88
878a4e49
AC
89 ignore (Mail.mclose m)
90 end
91 end
92 | doOne _ = raise Fail "Bad SQL row"
dda99898 93 in
878a4e49 94 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
95 C.close db;
96 OS.Process.success
878a4e49
AC
97 end handle C.Sql s => (print ("SQL failure: " ^ s ^ "\n");
98 OS.Process.failure)
dda99898
AC
99
100end