Changeset 17787 for main/waeup.kofa


Ignore:
Timestamp:
15 May 2024, 06:42:58 (6 months ago)
Author:
Henrik Bettermann
Message:

Add SessionConfigurationProcessor.
Add ConfigurationContainerProcessor.
Add ConfigurationContainerExporter.

Location:
main/waeup.kofa/trunk
Files:
2 added
14 edited

Legend:

Unmodified
Added
Removed
  • main/waeup.kofa/trunk/CHANGES.txt

    r17782 r17787  
    55=======================
    66
     7* Add `SessionConfigurationProcessor`.
     8
     9* Add `ConfigurationContainerProcessor`.
     10
    711* Add `ConfigurationContainerExporter`.
    812
     
    1721* Mangle referees and school grades when exporting applicants.
    1822
    19 * Add `ConfigurationExporter`.
     23* Add `SessionConfigurationExporter`.
    2024
    2125* Do not allow to add a study level if course registration has ended.
  • main/waeup.kofa/trunk/src/waeup/kofa/accesscodes/batching.py

    r17761 r17787  
    5050    factory_name = 'waeup.AccessCodeBatch'
    5151
    52     mode = None
    53 
    5452    def parentsExist(self, row, site):
    5553        return 'accesscodes' in site.keys()
     
    107105    location_fields = ['representation', 'batch_prefix', 'batch_num']
    108106    factory_name = 'waeup.AccessCode'
    109 
    110     mode = None
    111107
    112108    @property
  • main/waeup.kofa/trunk/src/waeup/kofa/applicants/batching.py

    r17774 r17787  
    106106    factory_name = 'waeup.Applicant'
    107107
    108     mode = None
    109 
    110108    @property
    111109    def available_fields(self):
  • main/waeup.kofa/trunk/src/waeup/kofa/browser/pages.py

    r17784 r17787  
    12331233    # We don't need to edit next matric integers in the base package.
    12341234    form_fields = grok.AutoFields(IConfigurationContainer).omit(
    1235         'frontpage_dict',
    12361235        'next_matric_integer',
    12371236        'next_matric_integer_2',
  • main/waeup.kofa/trunk/src/waeup/kofa/configuration.py

    r17782 r17787  
    3939    grok.implements(IConfigurationContainer)
    4040
     41    frontpage_dict = dict()
     42
    4143    def addSessionConfiguration(self, sessionconfiguration):
    4244        """Add a session configuration object.
     
    5254ConfigurationContainer = attrs_to_fields(ConfigurationContainer)
    5355
     56
     57class ConfigurationContainerFactory(grok.GlobalUtility):
     58    """A factory for configuration container. This factory is only needed
     59    for import.
     60    """
     61    grok.implements(IFactory)
     62    grok.name(u'waeup.ConfigurationContainer')
     63
     64    def __call__(self, *args, **kw):
     65        return ConfigurationContainer(*args, **kw)
     66
     67    def getInterfaces(self):
     68        return implementedBy(ConfigurationContainer)
     69
    5470class SessionConfiguration(grok.Model):
    5571    """
     
    88104
    89105    title = _(u'Base Configuration')
    90     fields = tuple(sorted(iface_names(IConfigurationContainer))) + ('curr_stud_id',)
     106    fields = tuple(sorted(iface_names(
     107        IConfigurationContainer, omit=['captcha',]))) + ('curr_stud_id',)
    91108
    92109    def mangle_value(self, value, name, context=None):
     
    106123        return self.close_outfile(filepath, outfile)
    107124
    108 class ConfigurationExporter(grok.GlobalUtility, ExporterBase):
    109     """The Configuration Exporter exports all configuration data. It iterates over all
    110     objects of the ``configuration`` container.
     125class SessionConfigurationExporter(grok.GlobalUtility, ExporterBase):
     126    """The Session Configuration Exporter exports all configuration data.
     127    It iterates over all objects of the ``configuration`` container.
    111128    """
    112129    grok.implements(ICSVExporter)
    113     grok.name('configurations')
     130    grok.name('sessionconfigurations')
    114131
    115132    title = _(u'Session Configurations')
     
    128145
    129146    def export_all(self, site, filepath=None):
    130         """Export configurations into filepath as CSV data.
     147        """Export session configurations into filepath as CSV data.
    131148
    132149        If `filepath` is ``None``, a raw string with CSV data is returned.
     
    135152        return self.export(configurations.values(), filepath)
    136153
    137 class ConfigurationProcessor(BatchProcessor):
    138     """The Configuration Processor processes session configuration objects in
    139     the ``configuration`` container.
     154class ConfigurationContainerProcessor(BatchProcessor):
     155    """The Configuration Container Processor processes processes the
     156    portal's base confoiguration data. This container exists in the portal.
     157    Thus only the update method is allowed.
    140158
    141159    """
     
    143161    grok.provides(IBatchProcessor)
    144162    grok.context(Interface)
    145     util_name = 'configurationprocessor'
     163    util_name = 'configurationcontainerupdater'
     164    grok.name(util_name)
     165
     166    name = u'ConfigurationConainer Processor (update only)'
     167    iface = IConfigurationContainer
     168    factory_name = 'waeup.ConfigurationContainer'
     169
     170    @property
     171    def available_fields(self):
     172        return tuple(
     173            sorted(iface_names(
     174                IConfigurationContainer,
     175                omit=['captcha',]))) + ('curr_stud_id',)
     176
     177    def parentsExist(self, row, site):
     178        return True
     179
     180    def entryExists(self, row, site):
     181        return True
     182
     183    def getParent(self, row, site):
     184        return site
     185
     186    def getEntry(self, row, site):
     187        return site['configuration']
     188
     189    def updateEntry(self, obj, row, site, filename):
     190        """Update obj to the values given in row.
     191        """
     192        if 'curr_stud_id' in row:
     193            studid = row.get('curr_stud_id')
     194            site['students']._curr_stud_id = int(studid)
     195        row.pop('curr_stud_id')
     196        super(ConfigurationContainerProcessor, self).updateEntry(
     197            obj, row, site, filename)
     198        return
     199
     200class SessionConfigurationProcessor(BatchProcessor):
     201    """The (Session) Configuration Processor processes session configuration
     202    objects in the ``configuration`` container.
     203    """
     204    grok.implements(IBatchProcessor)
     205    grok.provides(IBatchProcessor)
     206    grok.context(Interface)
     207    util_name = 'sessionconfigurationprocessor'
    146208    grok.name(util_name)
    147209
     
    149211    iface = ISessionConfiguration
    150212    factory_name = 'waeup.SessionConfiguration'
    151 
    152     mode = None
    153213
    154214    def parentsExist(self, row, site):
     
    181241        pass
    182242
     243
  • main/waeup.kofa/trunk/src/waeup/kofa/doctests/batchprocessing_browser.txt

    r17772 r17787  
    105105    'CertificateCourse Processor',
    106106    'Certificate Processor',
    107     'SessionConfiguration Processor',
     107    'ConfigurationConainer Processor (update only)',
    108108    'Course Processor',
    109109    'CourseTicket Processor',
     
    115115    'Public PDF Document Processor',
    116116    'Public REST Document Processor',
     117    'SessionConfiguration Processor',
    117118    'Student Processor',
    118119    'StudentStudyCourse Processor',
  • main/waeup.kofa/trunk/src/waeup/kofa/documents/batching.py

    r17763 r17787  
    6767
    6868    factory_name = None
    69 
    70     mode = None
    7169
    7270    @property
  • main/waeup.kofa/trunk/src/waeup/kofa/hostels/batching.py

    r17313 r17787  
    4545    location_fields = ['hostel_id',]
    4646    factory_name = 'waeup.Hostel'
    47 
    48     mode = None
    4947
    5048    def parentsExist(self, row, site):
     
    9896    location_fields = ['hostel_id', 'bed_id']
    9997    factory_name = None
    100 
    101     mode = None
    10298
    10399    @property
  • main/waeup.kofa/trunk/src/waeup/kofa/interfaces.py

    r17376 r17787  
    724724    """
    725725
     726    frontpage_dict = Attribute('Language translation dictionary with values in HTML format')
     727
    726728    name = schema.TextLine(
    727729        title = _(u'Name of University'),
     
    741743        default = default_html_frontpage,
    742744        constraint=validate_html,
    743         )
    744 
    745     frontpage_dict = schema.Dict(
    746         title = u'Content as language dictionary with values in html format',
    747         required = False,
    748         default = {},
    749745        )
    750746
  • main/waeup.kofa/trunk/src/waeup/kofa/students/tests/test_webservices.py

    r16393 r17787  
    11111111        self.assertEqual(xmlout, RESPONSE_XML)
    11121112        return
     1113
     1114    def test_get_student_info(self):
     1115        server = ServerProxy('http://mgr:mgrpw@localhost/app')
     1116        self.setup_student(self.student)
     1117        result = server.get_student_info('123')
     1118        self.assertEqual(result,
     1119            ['Anna Tester', 'CERT1', '1234', 'aa@aa.ng'])
     1120        REQUEST_XML = """\
     1121<?xml version="1.0"?>
     1122<methodCall>
     1123<methodName>get_student_info</methodName>
     1124<params>
     1125<param>
     1126<value><string>K1000000</string></value>
     1127</param>
     1128</params>
     1129</methodCall>"""
     1130        RESPONSE_XML = """\
     1131<?xml version='1.0'?>
     1132<methodResponse>
     1133<params>
     1134<param>
     1135<value><array><data>
     1136<value><string>Anna Tester</string></value>
     1137<value><string>CERT1</string></value>
     1138<value><string>1234</string></value>
     1139<value><string>aa@aa.ng</string></value>
     1140</data></array></value>
     1141</param>
     1142</params>
     1143</methodResponse>
     1144"""
     1145        xmlout = self.XMLRPC_post(REQUEST_XML)
     1146        self.assertEqual(xmlout, RESPONSE_XML)
     1147        return
     1148
     1149    def test_get_student_base_data(self):
     1150        server = ServerProxy('http://mgr:mgrpw@localhost/app')
     1151        result = server.get_student_base_data()
     1152        self.assertEqual(result,
     1153            [{'entry_mode': None,
     1154              'reg_number': '123',
     1155              'firstname': 'Anna',
     1156              'middlename': None,
     1157              'current_session': 2004,
     1158              'entry_session': 2004,
     1159              'certcode': 'CERT1',
     1160              'state': 'created',
     1161              'student_id': 'K1000000',
     1162              'faccode': 'fac1',
     1163              'lastname': 'Tester',
     1164              'matric_number': '234',
     1165              'depcode': 'dep1'}])
     1166        REQUEST_XML = """\
     1167<?xml version="1.0"?>
     1168<methodCall>
     1169<methodName>get_student_base_data</methodName>
     1170<params>
     1171</params>
     1172</methodCall>"""
     1173        RESPONSE_XML = """\
     1174<?xml version='1.0'?>
     1175<methodResponse>
     1176<params>
     1177<param>
     1178<value><array><data>
     1179<value><struct>
     1180<member>
     1181<name>entry_mode</name>
     1182<value><nil/></value></member>
     1183<member>
     1184<name>reg_number</name>
     1185<value><string>123</string></value>
     1186</member>
     1187<member>
     1188<name>firstname</name>
     1189<value><string>Anna</string></value>
     1190</member>
     1191<member>
     1192<name>middlename</name>
     1193<value><nil/></value></member>
     1194<member>
     1195<name>current_session</name>
     1196<value><int>2004</int></value>
     1197</member>
     1198<member>
     1199<name>entry_session</name>
     1200<value><int>2004</int></value>
     1201</member>
     1202<member>
     1203<name>certcode</name>
     1204<value><string>CERT1</string></value>
     1205</member>
     1206<member>
     1207<name>matric_number</name>
     1208<value><string>234</string></value>
     1209</member>
     1210<member>
     1211<name>state</name>
     1212<value><string>created</string></value>
     1213</member>
     1214<member>
     1215<name>faccode</name>
     1216<value><string>fac1</string></value>
     1217</member>
     1218<member>
     1219<name>lastname</name>
     1220<value><string>Tester</string></value>
     1221</member>
     1222<member>
     1223<name>student_id</name>
     1224<value><string>K1000000</string></value>
     1225</member>
     1226<member>
     1227<name>depcode</name>
     1228<value><string>dep1</string></value>
     1229</member>
     1230</struct></value>
     1231</data></array></value>
     1232</param>
     1233</params>
     1234</methodResponse>
     1235"""
     1236        xmlout = self.XMLRPC_post(REQUEST_XML)
     1237        self.assertEqual(xmlout, RESPONSE_XML)
     1238        return
  • main/waeup.kofa/trunk/src/waeup/kofa/students/webservices.py

    r16393 r17787  
    533533              )
    534534        return hitlist
     535
     536    # Data requested by the WAeUP team
     537
     538    @grok.require('waeup.xmlrpc')
     539    def get_student_base_data(self,
     540            current_session=None, current_level=None, certcode=None,
     541            current_mode=None, depcode=None, p_session=None):
     542        """Returns bursary data of a subset of students.
     543        """
     544        if not current_session:
     545            current_session = None
     546        if not current_level:
     547            current_level = None
     548        if not depcode:
     549            depcode = None
     550        if not certcode:
     551            certcode = None
     552        if not current_mode:
     553            current_mode = None
     554        hitlist = []
     555        cat = queryUtility(ICatalog, name='students_catalog')
     556        results = cat.searchResults(
     557                current_session=(current_session, current_session),
     558                current_level=(current_level, current_level),
     559                certcode=(certcode, certcode),
     560                current_mode=(current_mode, current_mode),
     561                depcode=(depcode, depcode),
     562                )
     563        for student in results:
     564            hitlist.append(dict(
     565                student_id=student.student_id,
     566                matric_number=student.matric_number,
     567                reg_number=student.reg_number,
     568                firstname=student.firstname,
     569                middlename=student.middlename,
     570                lastname=student.lastname,
     571                state=student.state,
     572                current_session=student.current_session,
     573                entry_session=student.entry_session,
     574                entry_mode=student.entry_mode,
     575                faccode=student.faccode,
     576                depcode=student.depcode,
     577                certcode=student.certcode,
     578                )
     579            )
     580        return hitlist
  • main/waeup.kofa/trunk/src/waeup/kofa/tests/test_configuration.py

    r17782 r17787  
    3030from waeup.kofa.configuration import (
    3131    ConfigurationContainer, SessionConfiguration, SessionConfigurationFactory,
    32     ConfigurationContainerExporter, ConfigurationExporter)
    33 from waeup.kofa.interfaces import(ICSVExporter,
     32    ConfigurationContainerExporter, SessionConfigurationExporter,
     33    ConfigurationContainerProcessor, SessionConfigurationProcessor)
     34from waeup.kofa.interfaces import(ICSVExporter, IBatchProcessor,
    3435    IConfigurationContainer, ISessionConfiguration, ISessionConfigurationAdd)
    3536
     
    124125        result = open(self.outfile, 'rb').read()
    125126        self.assertTrue(
    126             'acronym,captcha,carry_over,current_academic_session,email_admin,'
    127             'email_subject,export_disabled_message,frontpage,frontpage_dict,'
     127            'acronym,carry_over,current_academic_session,email_admin,'
     128            'email_subject,export_disabled_message,frontpage,'
    128129            'maintmode_enabled_by,name,name_admin,next_matric_integer,'
    129130            'next_matric_integer_2,next_matric_integer_3,'
    130131            'next_matric_integer_4,smtp_mailer,curr_stud_id\r\n'
    131             'WAeUP.Kofa,No captcha,0,,contact@waeup.org,Kofa Contact,,'
     132            'WAeUP.Kofa,0,,contact@waeup.org,Kofa Contact,,'
    132133            '"<h1>Welcome to WAeUP.Kofa\n<br>' in result
    133134            )
     
    138139    def test_ifaces(self):
    139140        # make sure we fullfill interface contracts
    140         obj = ConfigurationExporter()
     141        obj = SessionConfigurationExporter()
    141142        verify.verifyObject(ICSVExporter, obj)
    142         verify.verifyClass(ICSVExporter, ConfigurationExporter)
     143        verify.verifyClass(ICSVExporter, SessionConfigurationExporter)
    143144        return
    144145
    145146    def test_get_as_utility(self):
    146147        # we can get a faculty exporter as utility
    147         result = queryUtility(ICSVExporter, name="configurations")
     148        result = queryUtility(ICSVExporter, name="sessionconfigurations")
    148149        self.assertTrue(result is not None)
    149150        return
     
    154155        self.sessionconfig.clearance_fee = 3000.6
    155156        self.app['configuration'].addSessionConfiguration(self.sessionconfig)
    156         exporter = ConfigurationExporter()
     157        exporter = SessionConfigurationExporter()
    157158        exporter.export_all(self.app, self.outfile)
    158159        result = open(self.outfile, 'rb').read()
     
    164165            )
    165166        return
     167
     168BASECONFIG_SAMPLE_DATA = open(
     169    os.path.join(os.path.dirname(__file__), 'sample_baseconfig_data.csv'),
     170    'rb').read()
     171
     172BASECONFIG_HEADER_FIELDS = BASECONFIG_SAMPLE_DATA.split(
     173    '\n')[0].split(',')
     174
     175class BaseConfigurationProcessorTests(ConfigurationImportExportSetup):
     176
     177    layer = FunctionalLayer
     178
     179    def setUp(self):
     180        super(BaseConfigurationProcessorTests, self).setUp()
     181        self.processor = ConfigurationContainerProcessor()
     182
     183    def test_interface(self):
     184        # Make sure we fulfill the interface contracts.
     185        assert verify.verifyObject(IBatchProcessor, self.processor) is True
     186        assert verify.verifyClass(
     187            IBatchProcessor, ConfigurationContainerProcessor) is True
     188
     189    def test_import(self):
     190        self.csv_file = os.path.join(
     191            self.workdir, 'sample_baseconfig_data.csv')
     192        open(self.csv_file, 'wb').write(BASECONFIG_SAMPLE_DATA)
     193        num, num_warns, fin_file, fail_file = self.processor.doImport(
     194            self.csv_file, BASECONFIG_HEADER_FIELDS,'update')
     195        self.assertEqual(num_warns,0)
     196        configcontainer = self.processor.getEntry(dict(), self.app)
     197        self.assertEqual(configcontainer.frontpage, 'Hello World')
     198
     199SESSIONCONFIG_SAMPLE_DATA = open(
     200    os.path.join(os.path.dirname(__file__), 'sample_sessionconfig_data.csv'),
     201    'rb').read()
     202
     203SESSIONCONFIG_HEADER_FIELDS = SESSIONCONFIG_SAMPLE_DATA.split(
     204    '\n')[0].split(',')
     205
     206class SessionConfigurationProcessorTests(ConfigurationImportExportSetup):
     207
     208    layer = FunctionalLayer
     209
     210    def setUp(self):
     211        super(SessionConfigurationProcessorTests, self).setUp()
     212        self.processor = SessionConfigurationProcessor()
     213
     214    def test_interface(self):
     215        # Make sure we fulfill the interface contracts.
     216        assert verify.verifyObject(IBatchProcessor, self.processor) is True
     217        assert verify.verifyClass(
     218            IBatchProcessor, SessionConfigurationProcessor) is True
     219
     220    def test_import(self):
     221        self.csv_file = os.path.join(
     222            self.workdir, 'sample_sessionconfig_data.csv')
     223        open(self.csv_file, 'wb').write(SESSIONCONFIG_SAMPLE_DATA)
     224        num, num_warns, fin_file, fail_file = self.processor.doImport(
     225            self.csv_file, SESSIONCONFIG_HEADER_FIELDS,'create')
     226        self.assertEqual(num_warns,0)
     227        sessionconfig = self.processor.getEntry({'academic_session':'2017'}, self.app)
     228        self.assertEqual(sessionconfig.payment_disabled[0], 'sf_all')
     229
     230
  • main/waeup.kofa/trunk/src/waeup/kofa/university/batching.py

    r14724 r17787  
    6565    location_fields = ['code',]
    6666    factory_name = 'waeup.Faculty'
    67 
    68     mode = None
    6967
    7068    def parentsExist(self, row, site):
     
    192190    factory_name = 'waeup.Department'
    193191
    194     mode = None
    195 
    196192    def parentsExist(self, row, site):
    197193        if not 'faculties' in site.keys():
     
    244240    location_fields = ['code']
    245241    factory_name = 'waeup.Certificate'
    246 
    247     mode = None
    248242
    249243    @property
     
    328322    location_fields = ['code']
    329323    factory_name = 'waeup.Course'
    330 
    331     mode = None
    332324
    333325    def getParent(self, row, site):
     
    384376    factory_name = 'waeup.CertificateCourse'
    385377
    386     mode = None
    387 
    388378    def parentsExist(self, row, site):
    389379        if not 'faculties' in site.keys():
  • main/waeup.kofa/trunk/src/waeup/kofa/utils/converters.py

    r17764 r17787  
    242242        # Omit known dictionaries since there is no widget available
    243243        # for dictionary schema fields
    244         self.default_form_fields = form.Fields(iface).omit('description_dict')
     244        self.default_form_fields = form.Fields(iface).omit(
     245            'description_dict', 'frontpage_dict')
    245246        return
    246247
Note: See TracChangeset for help on using the changeset viewer.