(nil, nil) => %>No matches.<%
end
+elseif $"cmd" = "delinq" then
+ showNormal := false;
+ val dqs = Money.delinquentPledgers () %>
+<table>
+<tr> <th>Member</th> <th>Pledge</th> <th>Balance</th> </tr>
+<% foreach dq in dqs do %>
+<tr> <td><a href="user?id=<% #id dq %>"><% #name dq %></a></td> <td><% #shares dq %></td> <td>$<% #balance dq %></td> </tr>
+<% end %>
+</table>
+
+<a href="?lower=<% String.concatWith "," (List.map (fn dq => Int.toString (#id dq)) dqs) %>">Lower these pledges to 1</a>
+
+<% elseif $"lower" <> "" then
+ Money.resetPledges (List.map Web.stoi (String.tokens (fn ch => ch = #",") ($"lower")))
+
+ %><h3>Pledges reset.</h3><%
+
end %>
<% if showNormal then
<% if (Group.inGroupName "money" and $"lookback" = "") or $"audit" <> "" then %>
+<a href="?cmd=delinq">Drop pledges of delinquent members</a><br>
<a href="?lookback=20">Switch to regular member view</a><br>
<br><b><u>New transaction:</u></b><br>
val equalizeBalances : unit -> unit
val costBase : real -> real
+
+ val delinquentPledgers : unit -> { id : int, name : string, shares : int, balance : real } list
+ val resetPledges : int list -> unit
end
[share] => C.realFromSql share
| row => Init.rowError ("Bad costBase result", row)
+val monthlyCost = 900.0
+val graceMonths = 1
+
+fun delinquentPledgers () =
+ let
+ val costBase = costBase monthlyCost
+
+ fun makeRow [id, name, shares, amount] = {id = C.intFromSql id, name = C.stringFromSql name,
+ shares = C.intFromSql shares, balance = C.realFromSql amount}
+ | makeRow row = Init.rowError ("Bad delinquentPledgers", row)
+ in
+ C.map (getDb ()) makeRow ($`SELECT WebUserPaying.id, WebUserPaying.name, shares, amount
+ FROM WebUserPaying JOIN Balance ON Balance.id = bal
+ WHERE amount < shares * ^(C.realToSql costBase) * ^(C.intToSql graceMonths)
+ AND shares > 1
+ ORDER BY name`)
+ end
+
+fun resetPledges ids =
+ raise Fail ($`UPDATE WebUser SET shares = 1 WHERE id IN (^(String.concatWith ", " (List.map C.intToSql ids)))`)
+
end