1 <% @header [("title", ["MoneyMatters"])];
3 val root = Group.inGroupNum 0;
9 val id = Web.stoi ($"hist") %>
11 <tr> <td><b>Date</b></td> <td><b>Description</b></td> <td><b>Amount</b></td> </tr>
12 <% foreach (amount, trn) in Money.listUserTransactions id do %>
13 <tr> <td><% #d trn %></td> <td><a href="money?trn=<% #id trn %>"><% Web.html (#descr trn) %></a></td> <td><% amount %>/<% #amount trn %></td> </tr>
17 <% elseif $"cmd" = "list" then
18 val admin = Group.inGroupName "money";
19 showNormal := false %>
24 <tr> <td><b>Date</b></td> <td><b>Description</b></td> <td><b>Amount</b></td> <td><b>Last modified</b></td> <td><b>Participants</b></td> </tr>
25 <% foreach trn in Money.listTransactions () do %>
26 <tr> <td><% #d trn %></td> <td><a href="money?trn=<% #id trn %>"><% Web.html (#descr trn) %></a></td> <td><% #amount trn %></td> <td><% #stamp trn %></td>
27 <% switch Money.listChargesWithNames (#id trn) of
28 [(name, cha)] => %><td><a href="user?id=<% #usr cha %>"><% name %></a></td><%
29 | _ => %><td><i>multi</i></td><%
32 %><td><a href="money?modHosting=<% #id trn %>">[Hosting]</a> <a href="money?modPay=<% #id trn %>">[Payment]</a> <a href="money?modEven=<% #id trn %>">[Other]</a></td>
33 <td><a href="money?del=<% #id trn %>">[Delete]</a></td><%
39 <% elseif $"cmd" = "bals" then
40 showNormal := false %>
42 <h3>Active Balances</h3>
45 <% foreach bal in Balance.listOwnedBalances () do %>
46 <tr><td><% #name bal %></td> <td><% #amount bal %></td> <td>
47 <% switch Balance.listBalanceUsers (#id bal) of
50 %><a href="money?hist=<% #id user %>"><% Web.html (#name user) %></a><%
51 foreach user in users do
52 %>, <a href="money?hist=<% # id user %>"><% Web.html (#name user) %></a><%
58 <% elseif $"cmd" = "deadbals" then
59 showNormal := false %>
61 <h3>Retired Balances</h3>
64 <% foreach bal in Balance.listUnownedBalances () do %>
65 <tr><td><% #name bal %></td> <td><% #amount bal %></td> <td>
66 <% switch Balance.listBalanceUsers (#id bal) of
69 %><a href="user?id=<% #id user %>"><% Web.html (#name user) %></a> <a href="money?hist=<% #id user %>">[History]</a><%
70 foreach user in users do
71 %>, <a href="user?id=<% #id user %>"><% Web.html (#name user) %></a> <a href="money?hist=<% #id user %>">[History]</a><%
77 <% elseif $"cmd" = "nbals" then
79 val bals = Balance.listNegativeOwnedBalances () %>
81 <h3>Negative Active Balances (<% length bals %>)</h3>
84 <% foreach bal in bals do %>
85 <tr><td><% #name bal %></td> <td><% #amount bal %></td> <td>
86 <% switch Balance.listBalanceUsers (#id bal) of
89 %><a href="user?id=<% #id user %>"><% Web.html (#name user) %></a> <a href="money?hist=<% #id user %>">[History]</a><%
90 foreach user in users do
91 %>, <a href="user?id=<% #id user %>"><% Web.html (#name user) %></a> <a href="money?hist=<% #id user %>">[History]</a><%
97 <% elseif $"cmd" = "hosting" then
98 Group.requireGroupName "money";
99 showNormal := false %>
101 <h3>New hosting bill</h3>
103 <form action="money" method="post">
104 <input type="hidden" name="cmd" value="hosting2">
105 <table class="blanks">
106 <tr> <td>Description:</td> <td><input name="descr"></td> </tr>
107 <tr> <td>Date:</td> <td><input name="d"></td> </tr>
108 <tr> <td>Amount:</td> <td><input name="amount"></td> </tr>
109 <tr> <td>Free bandwidth cutoff (MB):</td> <td><input name="cutoff" value="200"></td> </tr>
110 <tr> <td>Cost/GB:</td> <td><input name="cost" value="4"></td> </tr>
111 <tr> <td>Member usage:</td> <td><textarea wrap="soft" name="usage" rows="24" cols="80"></textarea></td> </tr>
112 <tr> <td><input type="submit" value="Add"></td> </tr>
115 <% elseif $"cmd" = "hosting2" then
116 Group.requireGroupName "money";
117 val id = Money.addTransaction ($"descr", Util.neg (Web.stor ($"amount")), $"d");
118 Money.addHostingCharges {trn = id, cutoff = 1000 * Web.stoi ($"cutoff"), cost = Web.stor ($"cost"), usage = $"usage"};
120 %><h3>Hosting transaction added.</h3>
122 <% elseif $"modHosting" <> "" then
123 Group.requireGroupName "money";
125 val id = Web.stoi ($"modHosting");
126 val trn = Money.lookupTransaction id %>
128 <h3>Modify hosting bill</h3>
130 <form action="money" method="post">
131 <input type="hidden" name="saveHosting" value="<% id %>">
132 <table class="blanks">
133 <tr> <td>Description:</td> <td><input name="descr" value="<% Web.html (#descr trn) %>"></td> </tr>
134 <tr> <td>Date:</td> <td><input name="d" value="<% Web.html (#d trn) %>"></td> </tr>
135 <tr> <td>Amount:</td> <td><input name="amount" value="<% Util.neg (#amount trn) %>"></td> </tr>
136 <tr> <td>Free bandwidth cutoff (MB):</td> <td><input name="cutoff" value="200"></td> </tr>
137 <tr> <td>Cost/GB:</td> <td><input name="cost" value="4"></td> </tr>
138 <tr> <td>Member usage:</td> <td><textarea wrap="soft" name="usage" rows="24" cols="80"><%
139 switch Money.lookupHostingUsage id of
141 end %></textarea></td> </tr>
142 <tr> <td><input type="submit" value="Save"></td> </tr>
145 <% elseif $"saveHosting" <> "" then
146 Group.requireGroupName "money";
147 val id = Web.stoi ($"saveHosting");
148 val trn = Money.lookupTransaction id;
150 Money.clearCharges id;
151 Money.modTransaction {trn with descr = $"descr", d = $"d", amount = Util.neg (Web.stor ($"amount"))};
152 Money.addHostingCharges {trn = id, cutoff = 1000 * Web.stoi ($"cutoff"), cost = Web.stor ($"cost"), usage = $"usage"};
154 %><h3>Hosting transaction modified.</h3>
156 <% elseif $"cmd" = "evenForm" then
157 Group.requireGroupName "money";
158 showNormal := false %>
159 <h3>New generic/even transaction</h3>
160 <form action="money" method="post">
161 <input type="hidden" name="cmd" value="even">
162 <table class="blanks">
163 <tr> <td>Description:</td> <td><input name="descr"></td> </tr>
164 <tr> <td>Date:</td> <td><input name="d"></td> </tr>
165 <tr> <td>Amount:</td> <td><input name="amount"></td> </tr>
166 <tr> <td>Members:</td> <td><select name="usrs" size="5" multiple>
167 <% foreach usr in Init.listUsers () do %>
168 <option value="<% #id usr %>"><% #name usr %></option>
171 <tr> <td><input type="submit" value="Add"></td> </tr>
175 <% elseif $"cmd" = "pay" then
176 Group.requireGroupName "money";
177 val uid = (case $"user" of "" => ~1 | s => Web.stoi s);
178 showNormal := false %>
180 <h3>New member payment</h3>
182 <form action="money" method="post">
183 <input type="hidden" name="cmd" value="pay2">
184 <table class="blanks">
185 <tr> <td>Description:</td> <td><select name="descr">
186 <option<% if $"checkout" = "" then %> selected<% end %>>PayPal</option>
187 <option<% if $"checkout" <> "" then %> selected<% end %>>Google Checkout</option>
188 <option>Check</option>
189 <option>Direct transfer</option>
190 <option value="">Other:</option>
191 </select> <input name="descr2"></td> </tr>
192 <tr> <td>Date:</td> <td><input name="d" value="<% Web.html (Date.fmt "%B %d, %Y" (Date.fromTimeLocal (Time.now ()))) %>"></td> </tr>
193 <tr> <td>Amount:</td> <td><input name="amount"></td> </tr>
194 <tr> <td>Member:</td> <td><select name="usr">
195 <% foreach usr in Init.listUsers () do %>
196 <option value="<% #id usr %>"<% if #id usr = uid then %> selected<% end %>><% #name usr %></option>
199 <tr> <td><input type="submit" value="Add"></td> </tr>
203 <% elseif $"cmd" = "pay2" then
204 Group.requireGroupName "money";
205 val amount = Web.stor ($"amount");
206 val descr = $"descr";
207 val descr = iff descr = "" then $"descr2" else descr;
208 val id = Money.addTransaction ($"descr", amount, $"d");
209 Money.addCharge {trn = id, usr = Web.stoi ($"usr"), amount = amount};
210 Money.applyCharges id;
212 %><h3>Payment transaction added.</h3>
214 <% elseif $"modPay" <> "" then
215 Group.requireGroupName "money";
217 val id = Web.stoi ($"modPay");
218 val trn = Money.lookupTransaction id %>
220 <h3>Modify member payment</h3>
222 <form action="money" method="post">
223 <input type="hidden" name="savePay" value="<% id %>">
224 <table class="blanks">
225 <tr> <td>Description:</td> <td><input name="descr" value="<% Web.html (#descr trn) %>"></td> </tr>
226 <tr> <td>Date:</td> <td><input name="d" value="<% Web.html (#d trn) %>"></td> </tr>
227 <tr> <td>Amount:</td> <td><input name="amount" value="<% #amount trn %>"></td> </tr>
228 <tr> <td>Member:</td> <td><select name="usr">
229 <% foreach (sel, usr) in Money.listUsers (#id trn) do %>
230 <option value="<% #id usr %>"<% if sel then %> selected<% end %>><% #name usr %></option>
233 <tr> <td><input type="submit" value="Save"></td> </tr>
236 <% elseif $"savePay" <> "" then
237 Group.requireGroupName "money";
238 val id = Web.stoi ($"savePay");
239 val trn = Money.lookupTransaction id;
241 val amount = Web.stor ($"amount");
242 Money.clearCharges id;
243 Money.modTransaction {trn with descr = $"descr", d = $"d", amount = amount};
244 Money.addCharge {trn = id, usr = Web.stoi ($"usr"), amount = amount};
245 Money.applyCharges id;
247 %><h3>Member payment modified.</h3>
249 <% elseif $"cmd" = "evenForm" then
250 Group.requireGroupName "money";
251 showNormal := false %>
252 <h3>New generic/even transaction</h3>
253 <form action="money" method="post">
254 <input type="hidden" name="cmd" value="even">
255 <table class="blanks">
256 <tr> <td>Description:</td> <td><input name="descr"></td> </tr>
257 <tr> <td>Date:</td> <td><input name="d"></td> </tr>
258 <tr> <td>Amount:</td> <td><input name="amount"></td> </tr>
259 <tr> <td>Members:</td> <td><select name="usrs" size="5" multiple>
260 <% foreach usr in Init.listUsers () do %>
261 <option value="<% #id usr %>"><% #name usr %></option>
264 <tr> <td><input type="submit" value="Add"></td> </tr>
268 <% elseif $"cmd" = "even" then
269 Group.requireGroupName "money";
270 val id = Money.addTransaction ($"descr", Web.stor ($"amount"), $"d");
271 Money.addEvenCharges (id, map Web.stoi (Web.getMultiParam "usrs"))
273 %><h3>Even transaction added.</h3>
275 <% elseif $"modEven" <> "" then
276 Group.requireGroupName "money";
278 val trn = Money.lookupTransaction (Web.stoi ($"modEven")) %>
279 <h3>Modify even transaction</h3>
281 <form action="money" method="post">
282 <input type="hidden" name="saveEven" value="<% $"modEven" %>">
283 <table class="blanks">
284 <tr> <td>Description:</td> <td><input name="descr" value="<% Web.html (#descr trn) %>"></td> </tr>
285 <tr> <td>Date:</td> <td><input name="d" value="<% Web.html (#d trn) %>"></td> </tr>
286 <tr> <td>Amount:</td> <td><input name="amount" value="<% #amount trn %>"></td> </tr>
287 <tr> <td>Members:</td> <td><select name="usrs" size="5" multiple>
288 <% foreach (sel, usr) in Money.listUsers (#id trn) do %>
289 <option value="<% #id usr %>"<% if sel then %> selected<% end %>><% #name usr %></option>
292 <tr> <td><input type="submit" value="Save"></td> </tr>
296 <% elseif $"saveEven" <> "" then
297 Group.requireGroupName "money";
298 val id = Web.stoi ($"saveEven");
299 val trn = Money.lookupTransaction id;
300 Money.clearCharges id;
301 Money.modTransaction {trn with descr = $"descr", d = $"d", amount = Web.stor ($"amount")};
302 Money.addEvenCharges (id, map Web.stoi (Web.getMultiParam "usrs"))
304 %><h3>Even transaction modified</h3>
306 <% elseif $"del" <> "" then
307 Group.requireGroupName "money";
309 val trn = Money.lookupTransaction (Web.stoi ($"del")) %>
310 <h3>Are you sure you want to delete transaction <a href="money?trn=<% #id trn %>"><% Web.html (#descr trn) %></a>?</h3>
311 <a href="money?del2=<% $"del" %>">Yes, delete <% Web.html (#descr trn) %>!</a>
313 <% elseif $"del2" <> "" then
314 Group.requireGroupName "money";
315 val id = Web.stoi ($"del2");
316 val trn = Money.lookupTransaction id;
317 Money.clearCharges id;
318 Money.deleteTransaction id %>
319 <h3><% Web.html (#descr trn) %> deleted!</h3>
321 <% elseif $"cmd" = "equalize" then
322 Group.requireGroupName "money";
323 Money.equalizeBalances ();
324 %><h3>Balances equalized</h3>
326 <% elseif $"trn" <> "" then
328 val id = Web.stoi ($"trn");
329 val trn = Money.lookupTransaction id %>
330 <table class="blanks">
331 <tr> <td>TRN#:</td> <td><% id %></td> </tr>
332 <tr> <td>Description:</td> <td><% Web.html (#descr trn) %></td> </tr>
333 <tr> <td>Date:</td> <td><% #d trn %></td> </tr>
334 <tr> <td>Amount:</td> <td>$<% #amount trn %></td> </tr>
335 <tr> <td>Distribution:</td>
338 foreach (name, cha) in Money.listChargesWithNames id do
344 %><td><a href="user?id=<% #usr cha %>"><% name %></a></td> <td>$<% #amount cha %></td> </tr><%
348 <% elseif $"cmd" = "paypal" then
350 val apps = App.searchPaypal ($"email");
351 val users = Init.searchPaypal ($"email");
355 %><h3>Approved applications</h3>
357 <% foreach appl in apps do %>
359 <table class="blanks">
360 <tr> <td>Received:</td> <td><% #applied appl %></td> </tr>
361 <tr> <td>Approved by:</td> <td><%
364 foreach (id, name) in App.votes (#id appl) do
370 %><a href="user?id=<% id %>"><% name %></a><%
372 <tr> <td>Username:</td> <td><% #name appl %></td> </tr>
373 <tr> <td>Real name:</td> <td><% Web.html (#rname appl) %></td> </tr>
374 <tr> <td>E-mail address:</td> <td><a href="mailto:<% #email appl %>"><% #email appl %></a></td> </tr>
375 <% switch #paypal appl of
376 SOME s => %><tr> <td>PayPal:</td> <td><a href="mailto:<% s %>"><% s %></a></td> </tr>
378 switch #checkout appl of
379 SOME s => %><tr> <td>Google Checkout:</td> <td><a href="mailto:<% s %>"><% s %></a></td> </tr>
381 <tr> <td>Forward e-mail?</td> <td><% if #forward appl then %>yes<% else %>no<% end %></td> </tr>
382 <tr> <td>Proposed uses:</td> <td><% Web.htmlNl (#uses appl) %></td> </tr>
383 <tr> <td>Other information:</td> <td><% Web.htmlNl (#other appl) %></td> </tr>
387 <a href="apps?add=<% #id appl %>">Add this member.</a><br>
396 <% foreach user in users do %>
397 <li> <a href="user?id=<% #id user %>"><% #name user %></a> <a href="?cmd=pay&user=<% #id user %>">[add payment]</a></li>
401 switch (apps, users) of
402 (nil, nil) => %>No matches.<%
405 elseif $"cmd" = "checkout" then
407 val apps = App.searchCheckout ($"email");
408 val users = Init.searchCheckout ($"email");
412 %><h3>Approved applications</h3>
414 <% foreach appl in apps do %>
416 <table class="blanks">
417 <tr> <td>Received:</td> <td><% #applied appl %></td> </tr>
418 <tr> <td>Approved by:</td> <td><%
421 foreach (id, name) in App.votes (#id appl) do
427 %><a href="user?id=<% id %>"><% name %></a><%
429 <tr> <td>Username:</td> <td><% #name appl %></td> </tr>
430 <tr> <td>Real name:</td> <td><% Web.html (#rname appl) %></td> </tr>
431 <tr> <td>E-mail address:</td> <td><a href="mailto:<% #email appl %>"><% #email appl %></a></td> </tr>
432 <% switch #paypal appl of
433 SOME s => %><tr> <td>PayPal:</td> <td><a href="mailto:<% s %>"><% s %></a></td> </tr>
435 switch #checkout appl of
436 SOME s => %><tr> <td>Google Checkout:</td> <td><a href="mailto:<% s %>"><% s %></a></td> </tr>
438 <tr> <td>Forward e-mail?</td> <td><% if #forward appl then %>yes<% else %>no<% end %></td> </tr>
439 <tr> <td>Proposed uses:</td> <td><% Web.htmlNl (#uses appl) %></td> </tr>
440 <tr> <td>Other information:</td> <td><% Web.htmlNl (#other appl) %></td> </tr>
444 <a href="apps?add=<% #id appl %>">Add this member.</a><br>
453 <% foreach user in users do %>
454 <li> <a href="user?id=<% #id user %>"><% #name user %></a> <a href="?cmd=pay&user=<% #id user %>&checkout=1">[add payment]</a></li>
458 switch (apps, users) of
459 (nil, nil) => %>No matches.<%
464 <% if showNormal then
465 val you = Init.getUser();
466 val bal = Balance.lookupBalance (#bal you);
467 val deposit = Balance.depositAmount (#id bal) %>
469 <h3>Your balance: $<% Util.sub (#amount bal, deposit) %><br>
470 Deposit: $<% deposit %></b> (3 months of dues at your current <a href="pledge">pledge level</a>)</h3>
471 <% if (iff Group.inGroupName "money" then $"lookback" = "" else $"audit" <> "") then %><h3>Sum of all active balances: $<% Balance.sumOwnedBalances () %></h3><% end %>
473 <a href="money?cmd=list">List all transactions</a><br>
474 <a href="money?cmd=bals">List active balances</a><br>
475 <a href="money?cmd=nbals">List negative active balances</a><br>
476 <a href="money?cmd=deadbals">List retired balances</a><br>
478 <% if (Group.inGroupName "money" and $"lookback" = "") or $"audit" <> "" then %>
480 <a href="?lookback=20">Switch to regular member view</a><br>
482 <br><b><u>New transaction:</u></b><br>
483 <a href="money?cmd=hosting">Hosting bill</a><br>
484 <a href="money?cmd=pay">Payment from member</a><br>
485 <a href="money?cmd=evenForm">Generic/even</a><br>
487 <a href="money?cmd=equalize">Equalize balances</a><br>
490 <h3>Look up a PayPal e-mail address</h3>
493 <input type="hidden" name="cmd" value="paypal">
494 <input name="email"> <input type="submit" value="Look up">
497 <h3>Look up a Google Checkout e-mail address</h3>
500 <input type="hidden" name="cmd" value="checkout">
501 <input name="email"> <input type="submit" value="Look up">
504 <h3>Most recent transactions</h3>
507 <tr> <td><b>Date</b></td> <td><b>Description</b></td> <td><b>Amount</b></td> <td><b>Participants</b></td> <td><b>Replace</b></td> <td><b>Delete</b></td> </tr>
508 <% foreach trn in Money.listTransactionsLimit 20 do %>
509 <tr> <td><% #d trn %></td> <td><a href="money?trn=<% #id trn %>"><% Web.html (#descr trn) %></a></td> <td><% #amount trn %></td>
510 <% switch Money.listChargesWithNames (#id trn) of
511 [(name, cha)] => %><td><a href="user?id=<% #usr cha %>"><% name %></a></td><%
512 | _ => %><td><i>multi</i></td><%
514 <td><a href="money?modHosting=<% #id trn %>">[Hosting]</a> <a href="money?modPay=<% #id trn %>">[Payment]</a> <a href="money?modEven=<% #id trn %>">[Other]</a></td>
515 <td><a href="money?del=<% #id trn %>">[Delete]</a></td> </tr>
520 <a href="?audit=1">Switch to audit view</a><br>
521 <% val lookback = case $"lookback" of "" => 20 | lb => Web.stoi lb;
524 <h3>Your recent account activity</h3>
527 Show <input name="lookback" size="5" value="<% lookback %>"> most recent transactions.
528 <input type="submit" value="Show">
532 <tr> <td><b>Date</b></td> <td><b>Description</b></td> <td><b>Amount</b></td> </tr>
533 <% foreach (amount, trn) in Money.listUserTransactionsLimit (Init.getUserId (), lookback) do %>
534 <tr> <td><% #d trn %></td> <td><a href="money?trn=<% #id trn %>"><% Web.html (#descr trn) %></a></td> <td><% amount %>/<% #amount trn %></td> </tr>