コード例 #1
0
class TestMemberServicesIntegration(unittest.TestCase):
    """Unit test for the MemberService type
    """

    layer = INTEGRATION_TESTING

    def setUp(self):
        self.portal = self.layer['portal']
        self.services = self.portal._getOb('products_and_services')
        self.intids = queryUtility(IIntIds, context=self.portal)
        self.dao = MemberServicesDataAccess(self.portal)
        setRoles(self.portal, TEST_USER_ID, ['Member'])
        self.session = SESSION()

    def tearDown(self):
        count = self.session.query(MemberService).filter(
            MemberService.memberid == TEST_USER_ID
        ).delete()
        print 'Deleted %s' % count
        transaction.commit()
    
    def test_get_all_memberservices(self):
        db_ms = self.session.query(MemberService).all()
        all_ms = self.dao.get_all_memberservices()
        self.assertEquals(len(db_ms), len(all_ms))
        self.assertEquals(all_ms, db_ms)

    def test_get_memberservices(self):
        service = self.services.objectValues()[0]
        ms_args = self.get_ms_args(service, TEST_USER_ID)
        ms1 = self.dao.add_memberservice(**ms_args) 
        self.session.flush()
        ms1_db = self.get_memberservice(ms1.id)
        service_uids = [self.intids.getId(service),]
        memberid = TEST_USER_ID
        memberservices = \
            self.dao.get_memberservices(service_uids, memberid)
        self.assertEquals(memberservices, [ms1_db])

    def test_get_memberservices_by_subject(self):
        maths_services = \
            [s for s in self.services.objectValues() if 'maths' in s.subject]
        for count in range(0,3):
            service = maths_services[count]
            ms_args = self.get_ms_args(service, TEST_USER_ID)
            self.dao.add_memberservice(**ms_args)
        self.session.flush()

        science_services = \
            [s for s in self.services.objectValues() if 'science' in s.subject]
        for count in range(0,3):
            service = science_services[count]
            ms_args = self.get_ms_args(service, TEST_USER_ID)
            self.dao.add_memberservice(**ms_args)
        self.session.flush()

        memberservices = \
            self.dao.get_memberservices_by_subject(TEST_USER_ID, 'maths')
        self.assertEqual(len(memberservices), 3)
        memberservices = \
            self.dao.get_memberservices_by_subject(TEST_USER_ID, 'science')
        self.assertEqual(len(memberservices), 3)

    def test_get_memberservices_by_grade(self):
        grade_10_services = \
            [s for s in self.services.objectValues() if s.grade == 'grade-10']
        for count in range(0,3):
            service = grade_10_services[count]
            ms_args = self.get_ms_args(service, TEST_USER_ID)
            self.dao.add_memberservice(**ms_args)
        self.session.flush()

        memberservices = \
            self.dao.get_memberservices_by_grade(TEST_USER_ID, 'grade-10')
        self.assertEqual(len(memberservices), 3)

    def test_get_memberservices_by_subject_and_grade(self):
        grade_10_maths_services = \
            [s for s in self.services.objectValues() if s.grade == 'grade-10']
        grade_10_maths_services = \
            [s for s in grade_10_maths_services if 'maths' in s.subject]
        for count in range(0,3):
            service = grade_10_maths_services[count]
            ms_args = self.get_ms_args(service, TEST_USER_ID)
            self.dao.add_memberservice(**ms_args)
        self.session.flush()

        memberservices = \
            self.dao.get_memberservices_by_subject_and_grade(TEST_USER_ID,
                                                             'maths',
                                                             'grade-10')
        self.assertEqual(len(memberservices), 3)

        memberservices = \
            self.dao.get_memberservices_by_subject_and_grade(TEST_USER_ID,
                                                             'science',
                                                             'grade-10')
        self.assertEqual(len(memberservices), 0)

    def test_get_active_memberservices(self):
        for count in range(0,3):
            service = self.services.objectValues()[count]
            ms_args = self.get_ms_args(service, TEST_USER_ID)
            self.dao.add_memberservice(**ms_args)
        self.session.flush()
        
        now = datetime.now().date()
        td = timedelta(1)
        yesterday = now - td
        for count in range(3,6):
            service = self.services.objectValues()[count]
            ms_args = self.get_ms_args(service, TEST_USER_ID)
            ms_args['expiry_date'] = yesterday
            self.dao.add_memberservice(**ms_args)
        self.session.flush()
        
        active_memberservices = self.dao.get_active_memberservices(TEST_USER_ID)
        self.assertEquals(len(active_memberservices), 3)
        for ms in active_memberservices:
            self.assertEquals(ms.expiry_date, now)

    def test_get_active_memberservices_by_subject(self):
        now = datetime.now().date()
        td = timedelta(1)
        yesterday = now - td
        services = \
            [s for s in self.services.objectValues() if 'maths' in s.subject]
        for count in range(0,3):
            service = services[count]
            ms_args = self.get_ms_args(service, TEST_USER_ID)
            ms_args['expiry_date'] = now
            self.dao.add_memberservice(**ms_args)
        self.session.flush()

        services = \
            [s for s in self.services.objectValues() if 'science' in s.subject]
        for count in range(0,3):
            service = services[count]
            ms_args = self.get_ms_args(service, TEST_USER_ID)
            ms_args['expiry_date'] = yesterday
            self.dao.add_memberservice(**ms_args)
        self.session.flush()

        memberservices = \
            self.dao.get_active_memberservices_by_subject(TEST_USER_ID, 'maths')
        self.assertEqual(len(memberservices), 3)
        for ms in memberservices:
            self.assertEquals(ms.expiry_date, now)

    def test_get_active_memberservices_by_grade(self):
        now = datetime.now().date()
        td = timedelta(1)
        yesterday = now - td

        services = \
            [s for s in self.services.objectValues() if s.grade == 'grade-10']
        for count in range(0,3):
            service = services[count]
            ms_args = self.get_ms_args(service, TEST_USER_ID)
            ms_args['expiry_date'] = now
            self.dao.add_memberservice(**ms_args)
        self.session.flush()

        services = \
            [s for s in self.services.objectValues() if s.grade == 'grade-11']
        for count in range(0,3):
            service = services[count]
            ms_args = self.get_ms_args(service, TEST_USER_ID)
            ms_args['expiry_date'] = yesterday
            self.dao.add_memberservice(**ms_args)
        self.session.flush()

        memberservices = \
            self.dao.get_active_memberservices_by_grade(TEST_USER_ID, 'grade-10')
        self.assertEqual(len(memberservices), 3)
        for ms in memberservices:
            self.assertEquals(ms.expiry_date, now)

    def test_get_active_memberservices_by_subject_and_grade(self):
        now = datetime.now().date()
        td = timedelta(1)
        yesterday = now - td

        grade_10_maths_services = \
            [s for s in self.services.objectValues() if \
             s.grade == 'grade-10' and 'maths' in s.subject]
        for count in range(0,3):
            service = grade_10_maths_services[count]
            ms_args = self.get_ms_args(service, TEST_USER_ID)
            ms_args['expiry_date'] = now
            self.dao.add_memberservice(**ms_args)
        self.session.flush()

        grade_10_science_services = \
            [s for s in self.services.objectValues() if \
             s.grade == 'grade-10' and 'science' in s.subject]
        for count in range(0,3):
            service = grade_10_science_services[count]
            ms_args = self.get_ms_args(service, TEST_USER_ID)
            ms_args['expiry_date'] = yesterday
            self.dao.add_memberservice(**ms_args)
        self.session.flush()

        memberservices = \
            self.dao.get_memberservices_by_subject_and_grade(TEST_USER_ID,
                                                             'maths',
                                                             'grade-10')
        self.assertEqual(len(memberservices), 3)
        for ms in memberservices:
            self.assertEquals(ms.expiry_date, now)

    def test_get_expired_memberservices(self):
        now = datetime.now().date()
        for count in range(0,3):
            service = self.services.objectValues()[count]
            ms_args = self.get_ms_args(service, TEST_USER_ID)
            ms_args['expiry_date'] = now
            self.dao.add_memberservice(**ms_args)
        self.session.flush()
        
        td = timedelta(1)
        yesterday = now - td
        for count in range(3,6):
            service = self.services.objectValues()[count]
            ms_args = self.get_ms_args(service, TEST_USER_ID)
            ms_args['expiry_date'] = yesterday
            self.dao.add_memberservice(**ms_args)
        self.session.flush()
        
        expired_memberservices = self.dao.get_expired_memberservices(TEST_USER_ID)
        self.assertEquals(len(expired_memberservices), 3)
        for ms in expired_memberservices:
            self.assertEquals(ms.expiry_date, yesterday)

    def test_get_expired_memberservices_by_subject(self):
        now = datetime.now().date()
        td = timedelta(1)
        yesterday = now - td
        services = \
            [s for s in self.services.objectValues() if 'maths' in s.subject]
        for count in range(0,3):
            service = services[count]
            ms_args = self.get_ms_args(service, TEST_USER_ID)
            ms_args['expiry_date'] = now
            self.dao.add_memberservice(**ms_args)
        self.session.flush()

        services = \
            [s for s in self.services.objectValues() if 'science' in s.subject]
        for count in range(0,3):
            service = services[count]
            ms_args = self.get_ms_args(service, TEST_USER_ID)
            ms_args['expiry_date'] = yesterday
            self.dao.add_memberservice(**ms_args)
        self.session.flush()

        memberservices = \
            self.dao.get_expired_memberservices_by_subject(TEST_USER_ID, 'science')
        self.assertEqual(len(memberservices), 3)
        for ms in memberservices:
            self.assertEquals(ms.expiry_date, yesterday)

    def test_get_expired_memberservices_by_grade(self):
        now = datetime.now().date()
        td = timedelta(1)
        yesterday = now - td

        services = \
            [s for s in self.services.objectValues() if s.grade == 'grade-10']
        for count in range(0,3):
            service = services[count]
            ms_args = self.get_ms_args(service, TEST_USER_ID)
            ms_args['expiry_date'] = now
            self.dao.add_memberservice(**ms_args)
        self.session.flush()

        services = \
            [s for s in self.services.objectValues() if s.grade == 'grade-11']
        for count in range(0,3):
            service = services[count]
            ms_args = self.get_ms_args(service, TEST_USER_ID)
            ms_args['expiry_date'] = yesterday
            self.dao.add_memberservice(**ms_args)
        self.session.flush()

        memberservices = \
            self.dao.get_expired_memberservices_by_grade(TEST_USER_ID,
                                                         'grade-11')
        self.assertEqual(len(memberservices), 3)
        for ms in memberservices:
            self.assertEquals(ms.expiry_date, yesterday)

    def test_get_expired_memberservices_by_subject_and_grade(self):
        now = datetime.now().date()
        td = timedelta(1)
        yesterday = now - td

        grade_10_maths_services = \
            [s for s in self.services.objectValues() if \
             s.grade == 'grade-10' and 'maths' in s.subject]
        for count in range(0,3):
            service = grade_10_maths_services[count]
            ms_args = self.get_ms_args(service, TEST_USER_ID)
            ms_args['expiry_date'] = now
            self.dao.add_memberservice(**ms_args)
        self.session.flush()

        grade_10_science_services = \
            [s for s in self.services.objectValues() if \
             s.grade == 'grade-10' and 'science' in s.subject]
        for count in range(0,3):
            service = grade_10_science_services[count]
            ms_args = self.get_ms_args(service, TEST_USER_ID)
            ms_args['expiry_date'] = yesterday
            self.dao.add_memberservice(**ms_args)
        self.session.flush()

        memberservices = \
            self.dao.get_expired_memberservices_by_subject_and_grade(
                TEST_USER_ID, 'science', 'grade-10')
        self.assertEqual(len(memberservices), 3)
        for ms in memberservices:
            self.assertEquals(ms.expiry_date, yesterday)

    def test_get_memberservice_by_primary_key(self):
        service = self.services.objectValues()[0]
        ms_args = self.get_ms_args(service, TEST_USER_ID)
        ms1 = self.dao.add_memberservice(**ms_args) 
        self.session.flush()
        ms1_db = self.dao.get_memberservice_by_primary_key(ms1.id)
        self.assertEquals(ms1_db, self.get_memberservice(ms1.id))

    def test_add_memberservice(self):
        service = self.services.objectValues()[0]
        ms_args = self.get_ms_args(service, TEST_USER_ID)
        ms1 = self.dao.add_memberservice(**ms_args) 
        self.session.flush()
        ms1_db = self.get_memberservice(ms1.id)
        self.failUnless(IMemberService.providedBy(ms1_db))

    def test_adding_duplicate_memberservices(self):
        service = self.services.objectValues()[0]
        ms_args = self.get_ms_args(service, TEST_USER_ID)
        ms1 = self.dao.add_memberservice(**ms_args) 
        ms2 = self.dao.add_memberservice(**ms_args) 
        self.session.flush()
        ms1_db = self.get_memberservice(ms1.id)
        ms2_db = self.get_memberservice(ms2.id)
        self.failUnless(IMemberService.providedBy(ms1_db))

    def test_update_memberservice(self):
        service = self.services.objectValues()[0]
        ms_args = self.get_ms_args(service, TEST_USER_ID)
        ms1 = self.dao.add_memberservice(**ms_args) 
        self.session.flush()
        ms1_db = self.get_memberservice(ms1.id)
        ms1_db.title = 'new title'
        self.dao.update_memberservice(ms1_db)
        self.session.flush()
        ms1_db = self.get_memberservice(ms1.id)
        self.assertEquals(ms1_db.title, 'new title')

    def test_delete_memberservice(self):
        service = self.services.objectValues()[0]
        ms_args = self.get_ms_args(service, TEST_USER_ID)
        ms1 = self.dao.add_memberservice(**ms_args) 
        self.session.flush()
        ms1_db = self.get_memberservice(ms1.id)
        self.dao.delete_memberservice(ms1_db)
        ms1_db = self.get_memberservice(ms1.id)
        self.assertEquals(ms1_db, None)

    def test_related_service(self):
        service = self.services.objectValues()[0]
        ms_args = self.get_ms_args(service, TEST_USER_ID)
        ms1 = self.dao.add_memberservice(**ms_args) 
        self.session.flush()
        ms1_db = self.get_memberservice(ms1.id)
        self.failUnless(self.dao.related_service(ms1_db), service)

    def test_fti(self):
        fti = queryUtility(IDexterityFTI, name='emas.app.memberservice')
        self.assertEquals(None, fti)

    def test_schema(self):
        fti = queryUtility(IDexterityFTI, name='emas.app.memberservice')
        schema = fti.lookupSchema()
        self.assertEquals(None, schema)

    def test_factory(self):
        fti = queryUtility(IDexterityFTI, name='emas.app.memberservice')
        factory = fti.factory
        self.assertEquals(factory, None)
    
    def get_memberservice(self, memberservice_id):
        memberservices = self.session.query(MemberService).filter_by(
            id = memberservice_id).all()
        return memberservices and memberservices[0] or None

    def create_services(self):
        subjects = ['maths', 'science']
        grades = ['10', '11', '12']
        for subject in subjects:
            for count, grade in grades:
                props = {'service_type' : 'subscription',
                         'grade'        : grade,
                         'subject'      : subject,
                         'price'        : '111'}
                s_id = self.services.invokeFactory('emas.app.service',
                                                 '%s-%s' % (subject, grade),
                                                 **props)
                service = self.services._getOb(s_id)
                service.subject = props['subject']

    def get_ms_args(self, service, memberid):
        ms_args = {
            'memberid': memberid,
            'title': '%s for %s' % (service.title, memberid),
            'related_service_id': self.intids.getId(service),
            'expiry_date': datetime.now(),
        }
        return ms_args
コード例 #2
0
ファイル: practice.py プロジェクト: Siyavula/emas.theme
class Practice(BrowserView):
    """ Proxy for practice in Monassis
    """
    NUM_DAYS = 30

    implements(IPractice, IPublishTraverse)

    index = ViewPageTemplateFile('templates/practice.pt')

    def __init__(self, context, request):
        super(Practice, self).__init__(context, request)
        self.settings = queryUtility(IRegistry).forInterface(IEmasSettings)

    def __call__(self, *args, **kw):
        alsoProvides(self.request, IPracticeLayer)
        
        self.subject = \
            get_subject_from_path('/'.join(self.context.getPhysicalPath()))
        self.memberservices = []
        self.dao = MemberServicesDataAccess(self.context)
        self.practice_services = []
        self.accessto = ''

        portal_state = self.context.restrictedTraverse('@@plone_portal_state')
        path = self.request.get_header('PATH_INFO')

        member = portal_state.member()
        sm = getSecurityManager()
        self.ismanager = sm.checkPermission(
            permissions.ManagePortal, self.context) or False
        # give managers access to everything
        if self.ismanager:
            self.accessto = ('maths-grade-10,maths-grade-11,maths-grade-12,'
                        'science-grade-10,science-grade-11,science-grade-12')
        elif member.getId():
            self.memberservices, self.practice_services = \
                self.get_services(self.context, member.getId(), self.subject)
            self.accessto = self.get_accessto(self.practice_services)
        else:
            self.accessto = ''

        self.show_no_access_message = False

        if portal_state.anonymous():
            memberid = 'Anonymous'
        else:
            memberid = member.getId()
        log.info('X-Access-To for %s: %s' % (memberid, self.accessto))

        urlparts = urlparse(self.settings.practiceurl)
        practiceserver = urlparts.netloc
        
        path = self.request.get_header('PATH_INFO', '')
        if path and len(path) > 0:
            startpos = path.find(self.__name__)
            # strip the view name from the path
            path = path[startpos+len(self.__name__):]

        headers = {
            "Accept-Encoding": "identity",
            "Host": self.request.HTTP_HOST,
            "Connection": "close",
            "Cookie": self.request.HTTP_COOKIE,
            "Referer": self.request.HTTP_REFERER,
            "User-Agent": self.request.HTTP_USER_AGENT,
        }
        if not portal_state.anonymous():
            headers["Authorization"] = 'Basic ' + base64.b64encode(memberid)
            headers["X-Access-To"] = self.accessto

        # Forward GET and POST requests; complain for all other request types
        if self.request.method == 'GET':
            conn = httplib.HTTPConnection(practiceserver)
            conn.request("GET", path, headers=headers)
        elif self.request.method == 'POST':
            headers['Content-Type'] = 'application/x-www-form-urlencoded'
            conn = httplib.HTTPConnection(practiceserver, timeout=30)
            conn.request("POST", path,
                         body=urlencode(self.request.form.items()),
                         headers=headers)
        else:
            return self.request.RESPONSE.unauthorized()
        
        self.html = ''
        # Handle response from Monassis server
        response = conn.getresponse()

        # Force no caching of response, unless /static or /image
        if tuple(path.split('/')[:2]) not in [('','static'), ('','image')]:
            self.request.RESPONSE.appendHeader('Cache-Control',
                                               'no-store, no-cache')
        else:
            for key in ['Cache-Control', 'Expires']:
                value = response.getheader(key)
                if value is not None:
                    self.request.RESPONSE.appendHeader(key, value)

        if response.status == 200:   # Ok
            body = response.read()
            if response.msg.type == 'text/html':
                html = lxml.html.fromstring(body)
                html.make_links_absolute(base_url=self.settings.practiceurl,
                                         resolve_base_href=True)
                content = html.find('.//*[@id="content"]')
                if content is not None:
                    self.html = lxml.html.tostring(content)
                else:
                    self.html = body

                return self.index()
            else:
                resp = self.request.RESPONSE
                for key in ['Content-Length', 'Content-Type', 'Content-Disposition']:
                    value = response.msg.get(key)
                    if value is not None:
                        resp.setHeader(key, value)
                resp.write(body)

        elif response.status == 302: # Found
            urlparts = urlparse(response.msg.get('location'))
            redirto = '%s%s' % (self.context.absolute_url(), urlparts.path)
            if urlparts.fragment:
                redirto += '#%s' % urlparts.fragment
            return self.request.RESPONSE.redirect(redirto)
        elif response.status == 400: # Bad request
            raise BadRequest('The URL:%s is a bad request.' %path)
        elif response.status == 403: # Forbidden
            if portal_state.anonymous():
                return self.request.RESPONSE.unauthorized()
            else:
                log.info('User:%s not allowed to access URL:%s.' % 
                    (memberid, path))
                self.show_no_access_message = True
                self.add_noaccess_message()
                return self.index()
        elif response.status == 404: # NotFound
            raise NotFound('The URL:%s could not be found.' %path)
        else:
            log.warn('Upstream returned:%s for URL:%s. Status is not handled.' %
                (response.status, path))
    
    def add_first_login_message(self, member):
        last_login_time = member.getProperty('last_login_time')
        login_time = member.getProperty('login_time')
        # if it last login and current login are within 2 seconds of eachother, 
        # we consider this the 'first login'
        if login_time.micros() - last_login_time.micros() < 2000000:
            plone_utils = getToolByName(self.context, 'plone_utils')
            message = _(u'Have a look at the practice services.')
            plone_utils.addPortalMessage(message, 'info')
        
    def services_active(self):
        """ If the user has the ManagePortal permission.
            OR
            If the user has any active services.
            We want to display the practice service content.
        """
        return self.ismanager or len(self.memberservices) > 0
    
    def practice_service_messages(self):
        grades = [10, 11, 12]
        messages = []

        expiring_services = self.expiring_services()
        # Format messages about expiring services.
        if expiring_services.values():
            msg = ''
            num_days = self.number_of_days_until(expiring_services)
            if num_days < 1:
                days = 'today.'
            else:
                days = num_days > 1 and 'in %s days.' or 'in %s day.'
                days = days % num_days
            template = 'Your access to %s practice will expire '+days

            service_grades = expiring_services.keys()
            service_grades.sort()
            if service_grades == grades:
                msg = template % self.subject.capitalize()
            else:
                services = ' and '.join(['Grade %s' %s for s in service_grades])
                msg = template % services
            messages.append(msg)
        else:
            # no services expiring? Then don't show any messages.
            return []
        
        # Now, we do the formatting of the active services.
        active_services = self.active_services()
        # Remove all the services that we already reported on above.
        for grade in expiring_services.keys():
            active_services.pop(grade, None)
        if active_services.values():
            # flatten the list of memberservice lists
            memberservices = ListType(chain.from_iterable(active_services.values()))
            # sort according to expiry_date
            memberservices.sort(key=lambda service: service.expiry_date)
            # use the first expiry date
            formatted_expiry_date = \
                self.format_date(memberservices[0].expiry_date)

            msg = ''
            template = 'You will still have access to %s practice until %s.'
            service_grades = active_services.keys()
            service_grades.sort()
            services = ' and '.join(['Grade %s' %s for s in service_grades])
            msg = template % (services, formatted_expiry_date) 
            messages.append(msg)
        
        # Lastly, add a link to the order form.
        if expiring_services:
            messages.append(
                '<a href="/order">To extend your subscription, click here.</a>')

        return messages

    def format_date(self, expiry_date):
        if expiry_date.year == datetime.now().year:
            return expiry_date.strftime("%e %B")
        return expiry_date.strftime("%e %B %Y")

    def number_of_days_until(self, expiring_services):
        # flatten the list of memberservice lists
        memberservices = ListType(chain.from_iterable(expiring_services.values()))
        # sort according to expiry_date
        memberservices.sort(key=lambda service: service.expiry_date)
        # use the last expiry date
        expiry_date = memberservices[0].expiry_date
        now = datetime.now().date()
        delta = expiry_date - now
        return delta.days
        
    def expiring_services(self):
        now = datetime.now()
        expiring_services = {}
        for ms in self.memberservices:
            if self.is_expiring(now, ms):
                grade = int(self.dao.related_service(ms).grade.split('-')[-1])
                tmpservices = expiring_services.get(grade, [])
                tmpservices.append(ms)
                expiring_services[grade] = tmpservices
        return expiring_services
    
    def active_services(self):
        now = datetime.now()
        active_services = {}
        for ms in self.memberservices:
            if not self.is_expiring(now, ms):
                grade = int(self.dao.related_service(ms).grade.split('-')[-1])
                tmpservices = active_services.get(grade, [])
                tmpservices.append(ms)
                active_services[grade] = tmpservices
        return active_services
    
    def is_expiring(self, cutoff_date, memberservice):
        days = self.memberservice_expiry_threshold(memberservice)
        expiry_threshold = (cutoff_date + timedelta(days)).date()
        if memberservice.expiry_date <= expiry_threshold:
            return True
        return False
    
    def memberservice_expiry_threshold(self, memberservice):
        """ This method helps us decide when to show expiry warnings.

            For all services that have subscription_period of a YEAR or less,
            but not less than a MONTH, we want to show the message within the,
            'annual_expiry_warning_threshold'.

            For all services that have subscription_period of a MONTH or less,
            we want to show the message within the,
            'monthly_expiry_warning_threshold'. 
        """
        subperiod = self.dao.related_service(memberservice).subscription_period
        if subperiod <= MONTH:
            return self.settings.monthly_expiry_warning_threshold
        elif subperiod <= YEAR:
            return self.settings.annual_expiry_warning_threshold

    def get_services(self, context, userid, subject):
        memberservices = []
        services = []

        pps = self.context.restrictedTraverse('@@plone_portal_state')
        memberid = pps.member().getId()
        tmpservices = self.dao.get_active_memberservices_by_subject(memberid,
                                                                    subject)

        for ms in tmpservices:
            service = self.dao.related_service(ms)
            if service.access_path and '@@practice' in service.access_path:
                memberservices.append(ms)
                services.append(service)
        return memberservices, services

    def get_accessto(self, practice_services):
        accessto = ','.join(
            ['%s-%s' %(s.subject, s.grade) for s in practice_services]
        )
        return accessto

    def add_noaccess_message(self):
        # set a portal message
        plone_utils = getToolByName(self.context, 'plone_utils')
        message = _(u'You do not currently have access to this service.')
        plone_utils.addPortalMessage(message, 'info')
        return message

    def publishTraverse(self, request, name):
        """ consume the subpath """
        path = request['TraversalRequestNameStack']
        subpath = path[:]
        path[:] = []
        subpath.reverse()
        request.set('traverse_subpath', subpath)
        return self