42
42
from schooltool.app.security import ConfigurableCrowd
43
43
from schooltool.app.interfaces import ISchoolToolApplication
44
44
from schooltool.app.utils import vocabulary_titled
45
from schooltool.app.states import StateStartUpBase
46
from schooltool.app.states import RelationshipStates, RelationshipState
45
47
from schooltool.course import interfaces, booking
46
48
from schooltool.group.interfaces import IBaseGroup as IGroup
47
49
from schooltool.person.interfaces import IPerson
50
from schooltool.relationship import RelationshipProperty
48
51
from schooltool.relationship.relationship import getRelatedObjects
49
from schooltool.relationship import RelationshipProperty
52
from schooltool.relationship.temporal import ACTIVE, INACTIVE
53
from schooltool.securitypolicy.crowds import Crowd
50
54
from schooltool.schoolyear.subscriber import EventAdapterSubscriber
51
55
from schooltool.schoolyear.subscriber import ObjectEventAdapterSubscriber
52
56
from schooltool.schoolyear.interfaces import ISubscriber
53
57
from schooltool.schoolyear.interfaces import ISchoolYear
54
from schooltool.securitypolicy.crowds import Crowd, AggregateCrowd
55
from schooltool.securitypolicy.crowds import ClerksCrowd, AdministratorsCrowd
56
58
from schooltool.term.term import getNextTerm
57
59
from schooltool.term.interfaces import ITerm
59
61
from schooltool.common import SchoolToolMessage as _
64
SECTION_CONTAINERS_KEY = 'schooltool.course.section'
62
68
class InvalidSectionLinkException(Exception):
206
212
int_ids = getUtility(IIntIds)
207
213
term_id = str(int_ids.getId(term))
208
214
app = ISchoolToolApplication(None)
209
sc = app['schooltool.course.section'].get(term_id, None)
215
sc = app[SECTION_CONTAINERS_KEY].get(term_id, None)
211
sc = app['schooltool.course.section'][term_id] = SectionContainer()
217
sc = app[SECTION_CONTAINERS_KEY][term_id] = SectionContainer()
328
334
InstructorsCrowd(self.context).contains(principal))
331
class SectionCalendarViewers(AggregateCrowd):
332
"""Crowd of those who can see the section calendar."""
333
adapts(interfaces.ISection)
335
def crowdFactories(self):
336
return [ClerksCrowd, AdministratorsCrowd,
337
InstructorsCrowd, LearnersCrowd, SectionCalendarSettingCrowd]
340
337
class PersonLearnerAdapter(object):
341
338
implements(interfaces.ILearner)
408
406
_("Sections must be in consecutive terms"))
411
def getSectionRosterEventParticipants(event, rel_type):
412
if rel_type != event.rel_type:
414
if interfaces.ISection.providedBy(event.participant1):
415
return event.participant1, event.participant2
416
elif interfaces.ISection.providedBy(event.participant2):
417
return event.participant2, event.participant1
422
def propagateSectionInstructorAdded(event):
423
section, teacher = getSectionRosterEventParticipants(event,
424
relationships.URIInstruction)
427
if section.next and teacher not in section.next.instructors:
428
section.next.instructors.add(teacher)
431
def propagateSectionInstructorRemoved(event):
432
section, teacher = getSectionRosterEventParticipants(event,
433
relationships.URIInstruction)
436
if section.next and teacher in section.next.instructors:
437
section.next.instructors.remove(teacher)
440
def propagateSectionStudentAdded(event):
441
section, student = getSectionRosterEventParticipants(event,
442
relationships.URIMembership)
445
if section.next and student not in section.next.members:
446
section.next.members.add(student)
449
def propagateSectionStudentRemoved(event):
450
section, student = getSectionRosterEventParticipants(event,
451
relationships.URIMembership)
454
if section.next and student in section.next.members:
455
section.next.members.remove(student)
409
def propagateSectionInstructorsChange(event):
411
if not (link.rel_type == relationships.URIInstruction and
412
interfaces.ISection.providedBy(event.this)):
417
collection = section.next.instructors.all()
418
collection.on(event.date).relate(person, event.meaning, event.code)
421
def propagateSectionStudentsChange(event):
423
if not (link.rel_type == relationships.URIMembership and
424
interfaces.ISection.providedBy(event.this)):
429
collection = section.next.members.all()
430
collection.on(event.date).relate(person, event.meaning, event.code)
458
433
def copySection(section, target_term):
482
457
def LinkedSectionTermsVocabularyFactory():
483
458
return linkedSectionTermsVocabulary
461
class SectionMemberStatesStartup(StateStartUpBase):
463
states_name = 'section-membership'
464
states_title = _('Section Enrollment')
466
def populate(self, states):
467
states.add(_('Pending'), INACTIVE, 'p')
468
states.add(_('Enrolled'), ACTIVE, 'a')
469
states.add(_('Withdrawn'), INACTIVE, 'i')
470
states.add(_('Completed'), ACTIVE+COMPLETED, 'c')
471
states.describe(ACTIVE, _('Member'))
472
states.describe(ACTIVE+COMPLETED, _('Completed/Active'))
473
states.describe(INACTIVE+COMPLETED, _('Completed/Inactive'))
474
states.describe(INACTIVE, _('Inactive'))
477
class SectionInstructorStatesStartup(StateStartUpBase):
479
states_name = 'section-instruction'
480
states_title = _('Section Instruction')
482
def populate(self, states):
483
states.add(_('Instructor'), ACTIVE, 'a')
484
states.add(_('Substitute'), ACTIVE, 's')
485
states.add(_('Withdrawn'), INACTIVE, 'i')
486
states.describe(ACTIVE, _('Instructing'))
487
states.describe(INACTIVE, _('Removed'))