Commit | Line | Data |
---|---|---|
dda99898 AC |
1 | structure Remind :> REMIND = |
2 | struct | |
3 | ||
4 | open Config | |
5 | ||
6 | structure C = PgClient | |
7 | ||
878a4e49 AC |
8 | fun 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 | ||
8bc5f9f9 | 14 | val basePerMonth = 7.0 |
69ef6636 | 15 | val deposit = basePerMonth * 3.0 |
83e297c7 | 16 | |
dda99898 AC |
17 | fun main _ = |
18 | let | |
19 | val db = C.conn dbstring | |
20 | ||
878a4e49 AC |
21 | val totalShares = case C.oneRow db "SELECT SUM(shares) FROM WebUserPaying" of |
22 | [total] => C.intFromSql total | |
23 | | _ => raise Fail "Bad SUM(shares) row" | |
24 | ||
25 | fun doOne [user, members, shares, amount] = | |
26 | let | |
27 | val user = C.stringFromSql user | |
28 | val members = C.intFromSql members | |
29 | val shares = C.intFromSql shares | |
30 | val amount = C.realFromSql amount | |
31 | ||
83e297c7 | 32 | val perMonth = basePerMonth * real shares |
c8abf2d9 | 33 | val headsUp = deposit + perMonth * 2.0 |
878a4e49 | 34 | in |
bb40c5c6 | 35 | if amount >= headsUp then |
878a4e49 AC |
36 | () |
37 | else | |
38 | let | |
39 | val m = Mail.mopen () | |
40 | fun write msg = Mail.mwrite (m, msg) | |
41 | in | |
bb40c5c6 | 42 | if amount < deposit then |
878a4e49 AC |
43 | write "Subject: Your NEGATIVE HCoop balance\n" |
44 | else | |
45 | write "Subject: Your low HCoop balance\n"; | |
46 | write "From: HCoop Payment Reminder Robot <payment"; | |
47 | write emailSuffix; | |
48 | write ">\n"; | |
49 | write "To: "; | |
50 | write user; | |
51 | write emailSuffix; | |
52 | write "\nCc: payment@hcoop.net"; | |
53 | write "\n\n"; | |
54 | ||
bb40c5c6 | 55 | if amount < deposit then |
878a4e49 | 56 | (write "Your HCoop balance is negative. This means that you've paid less than you've\n"; |
bb40c5c6 AC |
57 | write "been charged to date, excluding your required deposit. If your account hasn't\n"; |
58 | write "been frozen yet, expect that to happen very soon. Our bylaws allow our board\n"; | |
59 | write "of directors to vote you out of the co-op, without any obligation to contact\n"; | |
60 | write "you first, when your balance stays negative for three months. Please make a\n"; | |
61 | write "payment as soon as possible, so that we don't need to do this!\n\n") | |
878a4e49 | 62 | else |
bb40c5c6 AC |
63 | (write "With our current dues projections, you have less than two months left until\n"; |
64 | write "your HCoop balance becomes negative, based on your sliding scale pledge amount.\n"; | |
65 | write "Please make a payment as soon as you can. We will freeze your account if your\n"; | |
66 | write "balance does become negative, and the board of directors will probably vote you\n"; | |
67 | write "out of the cooperative shortly thereafter if you don't make a payment.\n\n"); | |
878a4e49 AC |
68 | |
69 | write "Your balance: US$"; | |
bb40c5c6 | 70 | write (printReal (amount - deposit)); |
878a4e49 AC |
71 | write "\nTotal number of members linked to your balance: "; |
72 | write (Int.toString members); | |
73 | write "\nTotal pledge amount: "; | |
74 | write (Int.toString shares); | |
bb40c5c6 AC |
75 | write "\nDeposit: US$"; |
76 | write (printReal deposit); | |
77 | write "\nMinimum amount to pay to not see this message again for two months: US$"; | |
78 | write (printReal (headsUp - amount)); | |
dda99898 | 79 | |
8bc5f9f9 | 80 | write "\n\nThe deposit requirement was calculated as three months of dues at $7/mo..\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 |
ea5c7ca1 | 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 < " ^ C.realToSql deposit ^ " + " ^ C.realToSql (basePerMonth * 2.0) ^ " * SUM(WebUserPaying.shares)"); |
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 | |
100 | end |