Changeset 13251 for main/waeup.uniben/trunk
- Timestamp:
- 6 Sep 2015, 07:13:59 (9 years ago)
- Location:
- main/waeup.uniben/trunk/src/waeup/uniben
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
main/waeup.uniben/trunk/src/waeup/uniben/interswitch/tests.py
r13183 r13251 208 208 209 209 # Create hostel application ticket 210 self.browser.open(self.payments_path + '/addop')211 self.browser.getControl(name="form.p_category").value = ['hostel_application']212 self.browser.getControl("Create ticket").click()213 ctrl = self.browser.getControl(name='val_id')214 value = ctrl.options[3]215 self.browser.getLink(value).click()216 self.assertTrue(217 '<span>1000.0</span>' in self.browser.contents)218 self.student['payments'][value].approve()210 #self.browser.open(self.payments_path + '/addop') 211 #self.browser.getControl(name="form.p_category").value = ['hostel_application'] 212 #self.browser.getControl("Create ticket").click() 213 #ctrl = self.browser.getControl(name='val_id') 214 #value = ctrl.options[3] 215 #self.browser.getLink(value).click() 216 #self.assertTrue( 217 # '<span>1000.0</span>' in self.browser.contents) 218 #self.student['payments'][value].approve() 219 219 220 220 # Create temp maint fee ticket 221 self.browser.open(self.payments_path + '/addop')222 self.browser.getControl(name="form.p_category").value = ['tempmaint_1']223 self.browser.getControl("Create ticket").click()224 ctrl = self.browser.getControl(name='val_id')225 value = ctrl.options[4]226 self.browser.getLink(value).click()227 self.assertTrue(228 '<span>8150.0</span>' in self.browser.contents)221 #self.browser.open(self.payments_path + '/addop') 222 #self.browser.getControl(name="form.p_category").value = ['tempmaint_1'] 223 #self.browser.getControl("Create ticket").click() 224 #ctrl = self.browser.getControl(name='val_id') 225 #value = ctrl.options[4] 226 #self.browser.getLink(value).click() 227 #self.assertTrue( 228 # '<span>8150.0</span>' in self.browser.contents) 229 229 # Manager can access InterswitchForm 230 self.browser.getLink("CollegePAY", index=0).click()231 self.assertEqual(self.student['payments'][value].provider_amt, 0.0)232 self.assertEqual(self.student['payments'][value].gateway_amt, 150.0)233 self.assertTrue('<input type="hidden" name="pay_item_id" value="5705" />'234 in self.browser.contents)235 self.assertMatches('...Total Amount Authorized:...',236 self.browser.contents)237 self.assertTrue(238 '<input type="hidden" name="amount" value="815000" />'239 in self.browser.contents)240 self.assertTrue(241 '<item_detail item_id="1" item_name="Hostel Maintenance Fee" item_amt="800000" bank_id="129" acct_num="0014419432" />'242 in self.browser.contents)243 self.assertFalse(244 'item_name="BT Education"' in self.browser.contents)230 #self.browser.getLink("CollegePAY", index=0).click() 231 #self.assertEqual(self.student['payments'][value].provider_amt, 0.0) 232 #self.assertEqual(self.student['payments'][value].gateway_amt, 150.0) 233 #self.assertTrue('<input type="hidden" name="pay_item_id" value="5705" />' 234 # in self.browser.contents) 235 #self.assertMatches('...Total Amount Authorized:...', 236 # self.browser.contents) 237 #self.assertTrue( 238 # '<input type="hidden" name="amount" value="815000" />' 239 # in self.browser.contents) 240 #self.assertTrue( 241 # '<item_detail item_id="1" item_name="Hostel Maintenance Fee" item_amt="800000" bank_id="129" acct_num="0014419432" />' 242 # in self.browser.contents) 243 #self.assertFalse( 244 # 'item_name="BT Education"' in self.browser.contents) 245 245 246 246 # Create previous session fee ticket … … 284 284 self.browser.getControl("Create ticket").click() 285 285 ctrl = self.browser.getControl(name='val_id') 286 value = ctrl.options[ 5]286 value = ctrl.options[3] 287 287 self.browser.getLink(value).click() 288 288 self.assertTrue( -
main/waeup.uniben/trunk/src/waeup/uniben/students/tests/test_browser.py
r13110 r13251 19 19 import shutil 20 20 import tempfile 21 import pytz 22 from datetime import datetime, timedelta, date 21 23 from StringIO import StringIO 22 24 from hurry.workflow.interfaces import IWorkflowState, IWorkflowInfo 23 25 from zope.securitypolicy.interfaces import IPrincipalRoleManager 26 from zope.security.interfaces import Unauthorized 24 27 from zope.component.hooks import setSite, clearSite 25 28 from zope.component import getUtility, createObject … … 30 33 from waeup.kofa.students.tests.test_browser import StudentsFullSetup 31 34 from waeup.kofa.students.accommodation import BedTicket 35 from waeup.kofa.hostels.hostel import Hostel, Bed, NOT_OCCUPIED 32 36 from waeup.kofa.testing import FunctionalTestCase 33 37 from waeup.kofa.browser.tests.test_pdf import samples_dir … … 47 51 def setUp(self): 48 52 super(StudentUITests, self).setUp() 49 50 bedticket = BedTicket()51 bedticket.booking_session = 200452 bedticket.bed_type = u'any bed type'53 bedticket.bed = self.app['hostels']['hall-1']['hall-1_A_101_A']54 bedticket.bed_coordinates = u'My bed coordinates'55 self.student['accommodation'].addBedTicket(bedticket)56 53 57 54 def test_next_session_allowed(self): … … 253 250 self.browser.contents) 254 251 self.browser.open(self.payments_path + '/addop') 255 self.browser.getControl(256 name="form.p_category").value = ['tempmaint_1']257 self.browser.getControl("Create ticket").click()258 self.assertMatches('...You have not yet paid the hostel application fee...',259 self.browser.contents)260 self.browser.open(self.payments_path + '/addop')261 self.browser.getControl(name="form.p_category").value = ['hostel_application']262 self.browser.getControl("Create ticket").click()263 self.assertMatches('...ticket created...',264 self.browser.contents)265 ha_ticket = self.student['payments'].values()[2]266 ha_ticket.approve()267 self.browser.open(self.payments_path + '/addop')268 self.browser.getControl(269 name="form.p_category").value = ['tempmaint_1']270 self.browser.getControl("Create ticket").click()271 self.assertMatches('...ticket created...',272 self.browser.contents)273 self.browser.open(self.payments_path + '/addop')274 self.browser.getControl(275 name="form.p_category").value = ['tempmaint_2']276 self.browser.getControl("Create ticket").click()277 self.assertMatches('...ticket created...',278 self.browser.contents)279 self.browser.open(self.payments_path + '/addop')280 self.browser.getControl(281 name="form.p_category").value = ['tempmaint_3']282 self.browser.getControl("Create ticket").click()283 self.assertMatches('...ticket created...',284 self.browser.contents)285 self.browser.open(self.payments_path + '/addop')252 #self.browser.getControl( 253 # name="form.p_category").value = ['tempmaint_1'] 254 #self.browser.getControl("Create ticket").click() 255 #self.assertMatches('...You have not yet paid the hostel application fee...', 256 # self.browser.contents) 257 #self.browser.open(self.payments_path + '/addop') 258 #self.browser.getControl(name="form.p_category").value = ['hostel_application'] 259 #self.browser.getControl("Create ticket").click() 260 #self.assertMatches('...ticket created...', 261 # self.browser.contents) 262 #ha_ticket = self.student['payments'].values()[2] 263 #ha_ticket.approve() 264 #self.browser.open(self.payments_path + '/addop') 265 #self.browser.getControl( 266 # name="form.p_category").value = ['tempmaint_1'] 267 #self.browser.getControl("Create ticket").click() 268 #self.assertMatches('...ticket created...', 269 # self.browser.contents) 270 #self.browser.open(self.payments_path + '/addop') 271 #self.browser.getControl( 272 # name="form.p_category").value = ['tempmaint_2'] 273 #self.browser.getControl("Create ticket").click() 274 #self.assertMatches('...ticket created...', 275 # self.browser.contents) 276 #self.browser.open(self.payments_path + '/addop') 277 #self.browser.getControl( 278 # name="form.p_category").value = ['tempmaint_3'] 279 #self.browser.getControl("Create ticket").click() 280 #self.assertMatches('...ticket created...', 281 # self.browser.contents) 282 #self.browser.open(self.payments_path + '/addop') 286 283 # We can't test clearance payment ticket creation at the moment, 287 284 # since Uniben decided to deactivate clearance for ug students. … … 604 601 self.assertEqual(error, None) 605 602 606 #error, payment = utils.setPaymentDetails('hostel_maintenance', 603 bedticket = BedTicket() 604 bedticket.booking_session = 2004 605 bedticket.bed_type = u'any bed type' 606 bedticket.bed = self.app['hostels']['hall-1']['hall-1_A_101_A'] 607 bedticket.bed_coordinates = u'My bed coordinates' 608 self.student['accommodation'].addBedTicket(bedticket) 609 610 error, payment = utils.setPaymentDetails('hostel_maintenance', 611 self.student, None, None) 612 self.assertEqual(payment.p_level, 100) 613 self.assertEqual(payment.p_session, 2004) 614 self.assertEqual(payment.amount_auth, 876.0) 615 self.assertEqual(payment.p_item, u'My bed coordinates') 616 self.assertEqual(error, None) 617 618 error, payment = utils.setPaymentDetails('bed_allocation', 619 self.student, None, None) 620 self.assertEqual(payment.p_level, 100) 621 self.assertEqual(payment.p_session, 2004) 622 self.assertEqual(payment.amount_auth, 150.0) 623 self.assertEqual(payment.p_item, u'regular_male_re') 624 self.assertEqual(error, None) 625 626 #error, payment = utils.setPaymentDetails('hostel_application', 607 627 # self.student, None, None) 608 628 #self.assertEqual(payment.p_level, 100) 609 629 #self.assertEqual(payment.p_session, 2004) 610 #self.assertEqual(payment.amount_auth, 1 80.0)630 #self.assertEqual(payment.amount_auth, 1000.0) 611 631 #self.assertEqual(payment.p_item, u'') 612 632 #self.assertEqual(error, None) 613 633 614 #error, payment = utils.setPaymentDetails('bed_allocation', 634 #payment.approve() 635 #self.student['payments'][payment.p_id] = payment 636 637 #error, payment = utils.setPaymentDetails('tempmaint_1', 615 638 # self.student, None, None) 616 639 #self.assertEqual(payment.p_level, 100) 617 640 #self.assertEqual(payment.p_session, 2004) 618 #self.assertEqual(payment.amount_auth, 150.0)619 #self.assertEqual(payment.p_item, u' ')641 #self.assertEqual(payment.amount_auth, 8150.0) 642 #self.assertEqual(payment.p_item, u'Hall 1-4 M/F Ekehuan') 620 643 #self.assertEqual(error, None) 621 644 622 error, payment = utils.setPaymentDetails('hostel_application', 623 self.student, None, None) 624 self.assertEqual(payment.p_level, 100) 625 self.assertEqual(payment.p_session, 2004) 626 self.assertEqual(payment.amount_auth, 1000.0) 627 self.assertEqual(payment.p_item, u'') 628 self.assertEqual(error, None) 629 630 payment.approve() 631 self.student['payments'][payment.p_id] = payment 632 633 error, payment = utils.setPaymentDetails('tempmaint_1', 634 self.student, None, None) 635 self.assertEqual(payment.p_level, 100) 636 self.assertEqual(payment.p_session, 2004) 637 self.assertEqual(payment.amount_auth, 8150.0) 638 self.assertEqual(payment.p_item, u'Hall 1-4 M/F Ekehuan') 639 self.assertEqual(error, None) 640 641 error, payment = utils.setPaymentDetails('tempmaint_2', 642 self.student, None, None) 643 self.assertEqual(payment.p_level, 100) 644 self.assertEqual(payment.p_session, 2004) 645 self.assertEqual(payment.amount_auth, 12650.0) 646 self.assertEqual(payment.p_item, u'Hall 5 M/F') 647 self.assertEqual(error, None) 648 649 error, payment = utils.setPaymentDetails('tempmaint_3', 650 self.student, None, None) 651 self.assertEqual(payment.p_level, 100) 652 self.assertEqual(payment.p_session, 2004) 653 self.assertEqual(payment.amount_auth, 9650.0) 654 self.assertEqual(payment.p_item, u'Clinical Hostel') 655 self.assertEqual(error, None) 645 #error, payment = utils.setPaymentDetails('tempmaint_2', 646 # self.student, None, None) 647 #self.assertEqual(payment.p_level, 100) 648 #self.assertEqual(payment.p_session, 2004) 649 #self.assertEqual(payment.amount_auth, 12650.0) 650 #self.assertEqual(payment.p_item, u'Hall 5 M/F') 651 #self.assertEqual(error, None) 652 653 #error, payment = utils.setPaymentDetails('tempmaint_3', 654 # self.student, None, None) 655 #self.assertEqual(payment.p_level, 100) 656 #self.assertEqual(payment.p_session, 2004) 657 #self.assertEqual(payment.amount_auth, 9650.0) 658 #self.assertEqual(payment.p_item, u'Clinical Hostel') 659 #self.assertEqual(error, None) 656 660 657 661 error, payment = utils.setPaymentDetails('transfer', … … 901 905 open(path, 'wb').write(self.browser.contents) 902 906 print "Sample PDF transcript.pdf written to %s" % path 907 908 def test_student_accommodation(self): 909 self.browser.open(self.login_path) 910 self.browser.getControl(name="form.login").value = self.student_id 911 self.browser.getControl(name="form.password").value = 'spwd' 912 self.browser.getControl("Login").click() 913 # Students can add online booking fee payment tickets and open the 914 # callback view (see test_manage_payments). 915 self.browser.getLink("Payments").click() 916 self.browser.getLink("Add current session payment ticket").click() 917 self.browser.getControl(name="form.p_category").value = ['bed_allocation'] 918 self.browser.getControl("Create ticket").click() 919 ctrl = self.browser.getControl(name='val_id') 920 value = ctrl.options[0] 921 self.browser.getLink(value).click() 922 p_ticket = self.student['payments'].values()[0] 923 p_ticket.approveStudentPayment() 924 # The new HOS-0 pin has been created. 925 self.assertEqual(len(self.app['accesscodes']['HOS-0']),1) 926 pin = self.app['accesscodes']['HOS-0'].keys()[0] 927 ac = self.app['accesscodes']['HOS-0'][pin] 928 parts = pin.split('-')[1:] 929 sfeseries, sfenumber = parts 930 # Students can use HOS code and book a bed space with it ... 931 self.browser.open(self.acco_path) 932 # ... but not if booking period has expired ... 933 self.app['hostels'].enddate = datetime.now(pytz.utc) 934 self.browser.getLink("Book accommodation").click() 935 self.assertMatches('...Outside booking period: ...', 936 self.browser.contents) 937 self.app['hostels'].enddate = datetime.now(pytz.utc) + timedelta(days=10) 938 # ... or student data are incomplete ... 939 self.student['studycourse'].current_level = None 940 self.browser.getLink("Book accommodation").click() 941 self.assertMatches('...Your data are incomplete...', 942 self.browser.contents) 943 self.student['studycourse'].current_level = 100 944 # ... or student is not the an allowed state ... 945 self.browser.getLink("Book accommodation").click() 946 self.assertMatches('...You are in the wrong...', 947 self.browser.contents) 948 IWorkflowInfo(self.student).fireTransition('admit') 949 self.browser.getLink("Book accommodation").click() 950 self.assertMatches('...Activation Code:...', 951 self.browser.contents) 952 # Student can't use faked ACs ... 953 self.browser.getControl(name="ac_series").value = u'nonsense' 954 self.browser.getControl(name="ac_number").value = sfenumber 955 self.browser.getControl("Create bed ticket").click() 956 self.assertMatches('...Activation code is invalid...', 957 self.browser.contents) 958 # ... or ACs owned by somebody else. 959 ac.owner = u'Anybody' 960 self.browser.getControl(name="ac_series").value = sfeseries 961 self.browser.getControl(name="ac_number").value = sfenumber 962 self.browser.getControl("Create bed ticket").click() 963 self.assertMatches('...You are not the owner of this access code...', 964 self.browser.contents) 965 # The bed remains empty. 966 bed = self.app['hostels']['hall-1']['hall-1_A_101_A'] 967 self.assertTrue(bed.owner == NOT_OCCUPIED) 968 ac.owner = self.student_id 969 self.browser.getControl(name="ac_series").value = sfeseries 970 self.browser.getControl(name="ac_number").value = sfenumber 971 self.browser.getControl("Create bed ticket").click() 972 self.assertMatches('...Hall 1, Block A, Room 101, Bed A...', 973 self.browser.contents) 974 # Bed has been allocated. 975 self.assertTrue(bed.owner == self.student_id) 976 # BedTicketAddPage is now blocked. 977 self.browser.getLink("Book accommodation").click() 978 self.assertMatches('...You already booked a bed space...', 979 self.browser.contents) 980 # The bed ticket displays the data correctly. 981 self.browser.open(self.acco_path + '/2004') 982 self.assertMatches('...Hall 1, Block A, Room 101, Bed A...', 983 self.browser.contents) 984 self.assertMatches('...2004/2005...', self.browser.contents) 985 self.assertMatches('...regular_male_fr...', self.browser.contents) 986 self.assertMatches('...%s...' % pin, self.browser.contents) 987 # Students can open the pdf slip. 988 self.browser.open(self.browser.url + '/bed_allocation_slip.pdf') 989 self.assertEqual(self.browser.headers['Status'], '200 Ok') 990 self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf') 991 # Students can't relocate themselves. 992 self.assertFalse('Relocate' in self.browser.contents) 993 relocate_path = self.acco_path + '/2004/relocate' 994 self.assertRaises( 995 Unauthorized, self.browser.open, relocate_path) 996 # Students can't see the Remove button and check boxes. 997 self.browser.open(self.acco_path) 998 self.assertFalse('Remove' in self.browser.contents) 999 self.assertFalse('val_id' in self.browser.contents) 1000 # Students can pay maintenance fee now. 1001 self.browser.open(self.payments_path) 1002 self.browser.open(self.payments_path + '/addop') 1003 self.browser.getControl(name="form.p_category").value = ['hostel_maintenance'] 1004 self.browser.getControl("Create ticket").click() 1005 self.assertMatches('...Payment ticket created...', 1006 self.browser.contents) 1007 ctrl = self.browser.getControl(name='val_id') 1008 value = ctrl.options[0] 1009 # Maintennace fee is taken from the hostel object. 1010 self.assertEqual(self.student['payments'][value].amount_auth, 876.0) 1011 # If the hostel's maintenance fee isn't set, the fee is 1012 # taken from the session configuration object. 1013 self.app['hostels']['hall-1'].maint_fee = 0.0 1014 self.browser.open(self.payments_path + '/addop') 1015 self.browser.getControl(name="form.p_category").value = ['hostel_maintenance'] 1016 self.browser.getControl("Create ticket").click() 1017 ctrl = self.browser.getControl(name='val_id') 1018 value = ctrl.options[1] 1019 self.assertEqual(self.student['payments'][value].amount_auth, 987.0) 1020 return -
main/waeup.uniben/trunk/src/waeup/uniben/students/utils.py
r13248 r13251 21 21 from waeup.kofa.interfaces import (IKofaUtils, 22 22 CLEARED, RETURNING, PAID, REGISTERED, VALIDATED) 23 from waeup.kofa.utils.helpers import to_timezone 24 from waeup.kofa.students.utils import trans 23 25 from kofacustom.nigeria.students.utils import NigeriaStudentsUtils 24 26 from waeup.uniben.interfaces import MessageFactory as _ … … 48 50 return new_session, new_level 49 51 52 50 53 def checkAccommodationRequirements(self, student, acc_details): 51 54 if acc_details.get('expired', False): … … 62 65 else: 63 66 return _("Outside booking period.") 67 if not student.current_verdict in ('A', 'B'): 68 return _("Your data are eligible to book accommodation.") 64 69 if not acc_details.get('bt'): 65 70 return _("Your data are incomplete.") … … 84 89 return False 85 90 86 def _hostelApplicationPaymentMade(self, student, session):87 if len(student['payments']):88 for ticket in student['payments'].values():89 if ticket.p_state == 'paid' and \90 ticket.p_category == 'hostel_application' and \91 ticket.p_session == session:92 return True93 return False91 #def _hostelApplicationPaymentMade(self, student, session): 92 # if len(student['payments']): 93 # for ticket in student['payments'].values(): 94 # if ticket.p_state == 'paid' and \ 95 # ticket.p_category == 'hostel_application' and \ 96 # ticket.p_session == session: 97 # return True 98 # return False 94 99 95 100 def setPaymentDetails(self, category, student, … … 129 134 elif category == 'gown': 130 135 amount = academic_session.gown_fee 131 #elif category == 'bed_allocation': 132 # amount = academic_session.booking_fee 133 #elif category == 'hostel_maintenance': 134 # amount = academic_session.maint_fee 135 elif category == 'hostel_application': 136 amount = 1000.0 137 elif category.startswith('tempmaint'): 138 if not self._hostelApplicationPaymentMade( 139 student, student.current_session): 140 return _( 141 'You have not yet paid the hostel application fee.'), None 142 if category == 'tempmaint_1': 143 amount = 8150.0 144 elif category == 'tempmaint_2': 145 amount = 12650.0 146 elif category == 'tempmaint_3': 147 amount = 9650.0 136 elif category == 'bed_allocation': 137 p_item = self.getAccommodationDetails(student)['bt'] 138 amount = academic_session.booking_fee 139 elif category == 'hostel_maintenance': 140 amount = 0.0 141 bedticket = student['accommodation'].get( 142 str(student.current_session), None) 143 if bedticket: 144 p_item = bedticket.bed_coordinates 145 if bedticket.bed.__parent__.maint_fee > 0: 146 amount = bedticket.bed.__parent__.maint_fee 147 else: 148 # fallback 149 amount = academic_session.maint_fee 150 else: 151 # Should not happen because this is already checked 152 # in the browser module, but anyway ... 153 portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE 154 p_item = trans(_('no bed allocated'), portal_language) 155 #elif category == 'hostel_application': 156 # amount = 1000.0 157 #elif category.startswith('tempmaint'): 158 # if not self._hostelApplicationPaymentMade( 159 # student, student.current_session): 160 # return _( 161 # 'You have not yet paid the hostel application fee.'), None 162 # if category == 'tempmaint_1': 163 # amount = 8150.0 164 # elif category == 'tempmaint_2': 165 # amount = 12650.0 166 # elif category == 'tempmaint_3': 167 # amount = 9650.0 148 168 elif category == 'clearance': 149 169 p_item = student.certcode -
main/waeup.uniben/trunk/src/waeup/uniben/utils/utils.py
r13245 r13251 67 67 'schoolfee': 'School Fee', 68 68 'clearance': 'Acceptance Fee', 69 #'bed_allocation': 'Bed Allocation Fee',70 'hostel_application': 'Hostel Application Fee',69 'bed_allocation': 'Bed Allocation Fee', 70 #'hostel_application': 'Hostel Application Fee', 71 71 'hostel_maintenance': 'Hostel Maintenance Fee', 72 'tempmaint_1': 'Hall 1-4 M/F Ekehuan',73 'tempmaint_2': 'Hall 5 M/F',74 'tempmaint_3': 'Clinical Hostel',72 #'tempmaint_1': 'Hall 1-4 M/F Ekehuan', 73 #'tempmaint_2': 'Hall 5 M/F', 74 #'tempmaint_3': 'Clinical Hostel', 75 75 'transfer': 'Transfer Fee', 76 76 'gown': 'Gown Hire Fee', … … 83 83 'schoolfee': 'School Fee', 84 84 'clearance': 'Acceptance Fee', 85 'hostel_application': 'Hostel Application Fee', 86 'tempmaint_1': 'Hall 1-4 M/F Ekehuan Maintenance Fee', 87 'tempmaint_2': 'Hall 5 M/F Maintenance Fee', 88 'tempmaint_3': 'Clinical Hostel Maintenance Fee', 85 'bed_allocation': 'Bed Allocation Fee', 86 #'hostel_application': 'Hostel Application Fee', 87 'hostel_maintenance': 'Hostel Maintenance Fee', 88 #'tempmaint_1': 'Hall 1-4 M/F Ekehuan Maintenance Fee', 89 #'tempmaint_2': 'Hall 5 M/F Maintenance Fee', 90 #'tempmaint_3': 'Clinical Hostel Maintenance Fee', 89 91 'gown': 'Gown Hire Fee', 90 92 'application': 'Application Fee',
Note: See TracChangeset for help on using the changeset viewer.