</table>
</form>
+<% elseif $"cmd" = "dues" then
+ Group.requireGroupName "money";
+ showNormal := false %>
+
+<h3>Monthly dues</h3>
+
+<form action="money" method="post">
+<input type="hidden" name="cmd" value="dues2">
+<table class="blanks">
+<tr> <td>Description:</td> <td><input name="descr"></td> </tr>
+<tr> <td>Date:</td> <td><input name="d"></td> </tr>
+<tr> <td>Amount/pledge:</td> <td><input name="base"></td> </tr>
+<tr> <td><input type="submit" value="Add"></td> </tr>
+</table>
+
+<% elseif $"cmd" = "dues2" then
+ Group.requireGroupName "money";
+ Money.billDues {descr = $"descr", base = Web.stor ($"base"), date = $"d"};
+
+ %><h3>Dues debits added.</h3>
+
<% elseif $"cmd" = "even" then
Group.requireGroupName "money";
val id = Money.addTransaction ($"descr", Web.stor ($"amount"), $"d");
<br><b><u>New transaction:</u></b><br>
<a href="money?cmd=bill">Bill for the co-op</a><br>
-<a href="money?cmd=hosting">New hosting bill (old style)</a><br>
<a href="money?cmd=pay">Payment from member</a><br>
+<a href="money?cmd=dues">Monthly dues</a><br>
+<a href="money?cmd=hosting">New hosting bill (old style)</a><br>
<a href="money?cmd=evenForm">Generic/even</a><br>
<br>
<a href="money?cmd=equalize">Equalize balances</a><br>
val monthlyCost = 900.0
val graceMonths = 1
+val baseDues = 5.0
+
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)
+ WHERE amount < shares * ^(C.realToSql baseDues) * ^(C.intToSql graceMonths)
AND shares > 1
ORDER BY name`)
end
fun freezeworthyPledgers () =
let
- val costBase = costBase monthlyCost
+ val baseDues = 5.0
fun makeRow [id, name, amount] = {id = C.intFromSql id, name = C.stringFromSql name,
balance = C.realFromSql amount}
in
C.map (getDb ()) makeRow ($`SELECT WebUserPaying.id, WebUserPaying.name, amount
FROM WebUserPaying JOIN Balance ON Balance.id = bal
- WHERE amount >= ^(C.realToSql costBase) * ^(C.intToSql graceMonths)
- AND amount < ^(C.realToSql costBase) * ^(C.intToSql (graceMonths + 1))
+ WHERE amount >= ^(C.realToSql baseDues) * ^(C.intToSql graceMonths)
+ AND amount < ^(C.realToSql baseDues) * ^(C.intToSql (graceMonths + 1))
ORDER BY name`)
end
fun bootworthyPledgers () =
let
- val costBase = costBase monthlyCost
+ val baseDues = 5.0
fun makeRow [id, name, amount] = {id = C.intFromSql id, name = C.stringFromSql name,
balance = C.realFromSql amount}
in
C.map (getDb ()) makeRow ($`SELECT WebUserPaying.id, WebUserPaying.name, amount
FROM WebUserPaying JOIN Balance ON Balance.id = bal
- WHERE amount < ^(C.realToSql costBase) * ^(C.intToSql graceMonths)
+ WHERE amount < ^(C.realToSql baseDues) * ^(C.intToSql graceMonths)
ORDER BY name`)
end
+fun billDues {descr, base, date} =
+ let
+ val db = getDb ()
+ val paying =
+ case Group.groupNameToId "paying" of
+ NONE => raise Fail "No 'paying' group"
+ | SOME id => id
+
+ val shares =
+ case C.oneRow db ($`SELECT SUM(shares)
+ FROM WebUser JOIN Membership ON usr = WebUser.id AND grp = ^(C.intToSql paying)`) of
+ [n] => C.intFromSql n
+ | row => Init.rowError ("Bad addHostingCharges share count result", row)
+
+ val total = real shares * base
+
+ val give = addTransaction (descr, ~total, date)
+
+ fun doUser [uid, shares] =
+ let
+ val uid = C.intFromSql uid
+ val shares = C.intFromSql shares
+ in
+ addCharge {trn = give, usr = uid, amount = ~(base * real shares)}
+ end
+ | doUser r = Init.rowError ("Bad billDues/doUser row", r)
+
+ val receive = addTransaction (descr, total, date)
+
+ val hcoop = valOf (Init.userNameToId "hcoop")
+ in
+ C.app db doUser ($`SELECT id, shares
+ FROM WebUser JOIN Membership ON usr = WebUser.id AND grp = ^(C.intToSql paying)`);
+ applyCharges give;
+
+ addCharge {trn = receive, usr = hcoop, amount = total};
+ applyCharges receive
+ end
+
end
val user = Init.getUser () %>
-<p>HCoop divides expenses among members based on a "sliding scale"-style scheme. We charge you only for our concrete expenses, not adding any expenses beyond what we pay to service providers and vendors. Whenever a concrete expense needs to be paid for, we divide it among the members based on how much each of you has pledged on this web page. Your pledge is a whole number 1 or higher which you can think of as indicating how many times the amount paid by the lowest-contributing members you are willing to pay. Concretely, every expense is divided by the sum of all members' pledges, and each member is charged an amount equal to the result of that division times his pledge number. This way <i>everyone's</i> monthly costs go down automatically as we gain new members.</p>
+<p>Base HCoop membership dues are set at $5/mo.. On this page, you can set a <i>pledge amount</i> above one, so that you pay 5<i>N</i> dollars a month, where <i>N</i> is your pledge amount, to help offset costs for members with more stringent budgets. If the members listed below weren't making extra pledges, we would need to increase the base dues amount of $5 to cover our costs.</p>
+
+<!--p>HCoop divides expenses among members based on a "sliding scale"-style scheme. We charge you only for our concrete expenses, not adding any expenses beyond what we pay to service providers and vendors. Whenever a concrete expense needs to be paid for, we divide it among the members based on how much each of you has pledged on this web page. Your pledge is a whole number 1 or higher which you can think of as indicating how many times the amount paid by the lowest-contributing members you are willing to pay. Concretely, every expense is divided by the sum of all members' pledges, and each member is charged an amount equal to the result of that division times his pledge number. This way <i>everyone's</i> monthly costs go down automatically as we gain new members.</p-->
<h2>Set your pledge number</h2>
<form method="post">
</form>
<h2>Calculate your share of an expense</h2>
+
+<p>This form is mostly of historical interest, since we've switched to a flat dues scheme.</p>
+
<form method="post">
<input type="hidden" name="cmd" value="calc">
$<input name="amt" size="7" value="750">