Exemple #1
0
def planning_view(request):
    period = 'now'
    if request.GET.get('year') in {'past1', 'past2'}:
        period = request.GET['year']
    pools = list(Pool.all())
    poolid2index = dict()
    poolids = set()
    for pool in pools:
        poolids.add(_id(pool))
    # TODO reduce number of queries
    current = date_to_midnight(now() - datetime.timedelta(days=1))
    past1year = date_to_midnight(now() - datetime.timedelta(days=356))
    past2year = date_to_midnight(now() - datetime.timedelta(days=356*2))
    if period == 'now':
        start = current
        end = None
    elif period == 'past1':
        start = past1year
        end = current
    elif period == 'past2':
        start = past2year
        end = past1year
    event_entities = list(Event.all_in_period(start, end))
    used_pools = set()
    for e in event_entities:
        for v in e.vacancies():
            used_pools.add(v.pool_id)
    pools_tpl = []
    i = 0
    for pool in pools:
        if _id(pool) not in used_pools:
            continue
        poolid2index[pool._id] = i
        pools_tpl.append(pool)
        i += 1
    events = list()
    for e in event_entities:
        ei = {'id': _id(e),
              'name': e.name,
              'datetime': e.date,
              'kind': e.kind,
              'vacancies': dict()}
        for index in poolid2index.values():
            ei['vacancies'][index] = list()
        for v in e.vacancies():
            ei['vacancies'][poolid2index[v.pool_id]].append({
                'begin': v.begin,
                'begin_time': v.begin_time,
                'end_time': v.end_time,
                'assignee': v.assignee.humanName
                if v.assignee else "?"})
        for index in poolid2index.values():
            ei['vacancies'][index].sort(key=lambda x: x['begin'])
        events.append(ei)
    events.sort(key=lambda x: x['datetime'])
    return render_to_response('planning/overview.html',
                              {'events': events,
                               'pools': pools_tpl,
                               'period': period},
                              context_instance=RequestContext(request))
Exemple #2
0
def generate_postfix_map(giedo):
        tbl = dict() # the virtual map
        non_mailman_groups = {}
        dt_now = now()
        id2email = {}
        # handle the straightforward cases
        for e in Es.all():
                if e.canonical_email is None or e.name is None:
                        continue
                id2email[e._id] = e.canonical_email
                for nm in e.other_names:
                        tbl["%s@%s" % (nm, MAILDOMAIN)] = (e.canonical_email,)
                if e.type == 'user':
                        tbl[e.canonical_email] = (e.primary_email,)
                elif e.type == 'group':
                        if e.got_mailman_list:
                                tbl[e.canonical_email] = ('%s@%s' % (
                                        str(e.name), LISTS_MAILDOMAIN),)
                        else:
                                tbl[e.canonical_email] = []
                                non_mailman_groups[e._id] = e
                else:
                        logging.warn("postfix: unhandled type: %s" % e.type)
        # handle the non-mailman groups
        for rel in Es.query_relations(_with=non_mailman_groups.keys(),
                        _from=dt_now, until=dt_now, how=None):
                e = non_mailman_groups[rel['with']]
                email = id2email.get(rel['who'])
                if email is not None:
                        tbl[e.canonical_email].append(email)
        return tbl
Exemple #3
0
def generate_postfix_map(giedo):
    tbl = dict()  # the virtual map
    non_mailman_groups = {}
    dt_now = now()
    id2email = {}
    # handle the straightforward cases
    for e in Es.all():
        if e.canonical_email is None:
            continue
        id2email[e._id] = e.canonical_email
        for nm in e.other_names:
            tbl["%s@%s" % (nm, settings.MAILDOMAIN)] = (e.canonical_email,)
        if e.type == 'user':
            tbl[e.canonical_email] = (e.email,)
        elif e.type == 'group':
            if e.got_mailman_list and e.name:
                tbl[e.canonical_email] = ('%s@%s' % (
                    str(e.name), settings.LISTS_MAILDOMAIN),)
            else:
                tbl[e.canonical_email] = []
                non_mailman_groups[e._id] = e
        else:
            logging.warn("postfix: unhandled type: %s" % e.type)
        id_email = "%s@%s" % (e.id, settings.MAILDOMAIN)
        if id_email not in tbl:
            tbl[id_email] = (e.canonical_email,)
    # handle the non-mailman groups
    for rel in Es.query_relations(_with=list(non_mailman_groups),
                                  _from=dt_now, until=dt_now, how=None):
        e = non_mailman_groups[rel['with']]
        email = id2email.get(rel['who'])
        if email is not None:
            tbl[e.canonical_email].append(email)
    return tbl
Exemple #4
0
def relation_begin(request):
    # TODO We should use Django forms, or better: use sweet Ajax
    d = {}
    for t in ('who', 'with', 'how'):
        if t not in request.POST:
            raise ValueError, "Missing attr %s" % t
        if t == 'how' and request.POST[t] == 'null':
            d[t] = None
        else:
            d[t] = _id(request.POST[t])
    if not Es.user_may_begin_relation(request.user, d['who'], d['with'],
                                                                d['how']):
        raise PermissionDenied
    # Check whether such a relation already exists
    dt = now()
    ok = False
    try:
        next(Es.query_relations(who=d['who'], _with=d['with'],
            how=d['how'], _from=dt, until=DT_MAX))
    except StopIteration:
        ok = True
    if not ok:
        raise ValueError, "This relation already exists"
    # Add the relation!
    Es.add_relation(d['who'], d['with'], d['how'], dt, DT_MAX)
    giedo.sync()
    return redirect_to_referer(request)
Exemple #5
0
def relation_begin(request):
    # TODO We should use Django forms, or better: use sweet Ajax
    d = {}
    for t in ("who", "with", "how"):
        if t not in request.POST:
            raise ValueError, "Missing attr %s" % t
        if t == "how" and (not request.POST[t] or request.POST[t] == "null"):
            d[t] = None
        else:
            d[t] = _id(request.POST[t])
    if not Es.user_may_begin_relation(request.user, d["who"], d["with"], d["how"]):
        raise PermissionDenied

    # Check whether such a relation already exists
    dt = now()
    ok = False
    try:
        next(Es.query_relations(who=d["who"], _with=d["with"], how=d["how"], _from=dt, until=DT_MAX))
    except StopIteration:
        ok = True
    if not ok:
        raise ValueError, _("Deze relatie bestaat al")

    # Add the relation!
    relation_id = Es.add_relation(d["who"], d["with"], d["how"], dt, DT_MAX)

    # Notify informacie
    # TODO (rik) leave out 'als lid'
    Es.notify_informacie("relation_begin", request.user, relation=relation_id)

    giedo.sync_async(request)
    return redirect_to_referer(request)
Exemple #6
0
def generate_postfix_slm_map(giedo):
    # We generate the postfix "sender_login_maps".
    # This is used to decide by postfix whether a given user is allowed to
    # send e-mail as if it was coming from a particular e-mail address.
    # It is a dictionary { <email address> : [ <allowed user>, ... ] }
    tbl = dict()
    dt_now = now()
    # Get all users
    ulut = dict()
    # We only allow members to send e-mail
    for u in Es.by_name('leden').get_members():
        ulut[u._id] = u
        for name in u.names:
            if str(name) not in tbl:
                tbl[str(name)] = set()
            tbl[str(name)].add(str(u.name))
    # There are two kind of groups: groups whose members are allowed to
    # send e-mail as if coming from the group itself and those where this
    # is not allowed.  For convenience, lets call the first kind the
    # impersonatable groups.
    # Get all impersonatable groups and create a look-up-table for
    # group membership
    gs = list()
    for g in Es.groups():
        # TODO add a tag to force a group either impersonatable or not
        if not g.got_mailman_list:
            gs.append(g)
    mrels = Es.query_relations(how=None, _with=gs, _from=dt_now, until=dt_now)
    mlut = dict()
    for g in gs:
        mlut[g._id] = []
    for mrel in mrels:
        mlut[mrel['with']].append(mrel['who'])
    # Flatten out group membership.  For instance: if Giedo is in Kasco
    # and Kasco is in Boekenlezers, then Giedo is also in the Boekenlezers
    # unix group.
    # But first split the mlut graph into a impersonatable group
    # and a non-group subgraph.
    mlut_g = {}     # { <group> : <members that are impersonatable groups> }
    mlut_u = {}    # { <group> : <members that are users> }
    for g_id in mlut:
        mlut_g[g_id] = [c for c in mlut[g_id] if c in mlut]
        mlut_u[g_id] = [c for c in mlut[g_id] if c in ulut]
    mlut_g_tc = tc(mlut_g)  # transitive closure
    for g in gs:
        to_consider = tuple(mlut_g_tc[g._id]) + (g._id,)
        for sg_id in to_consider:
            for u_id in mlut_u[sg_id]:
                for name in g.names:
                    if str(name) not in tbl:
                        tbl[str(name)] = set()
                    tbl[str(name)].add(str(ulut[u_id].name))
    # Clean up tbl to return.
    ret = {}
    for name, users in six.iteritems(tbl):
        if not users:
            continue
        ret["%s@%s" % (name, settings.MAILDOMAIN)] = tuple(users)
    return ret
Exemple #7
0
 def add_note(self, what, by=None):
     dt = now()
     note = Note({'note': what,
                  'on': self._id,
                  'by': None if by is None else _id(by),
                  'at': dt})
     note.save()
     return note
Exemple #8
0
def notify_informacie(event, entity=None, relation=None):
    data = {'when': now(), 'event': event}
    if relation is not None:
        data['rel'] = _id(relation)
    elif entity is not None:
        data['entity'] = _id(entity)
    else:
        raise ValueError, 'supply either entity or relation'
    incol.insert(data)
Exemple #9
0
 def add_note(self, what, by=None):
     dt = now()
     Note({'note': what,
           'on': self._id,
           'open': True,
           'by': None if by is None else _id(by),
           'at': dt,
           'closed_by': None,
           'closed_at': None}).save()
Exemple #10
0
def notify_informacie(event, entity=None, relation=None):
    data = {'when': now(), 'event': event}
    if relation is not None:
        data['rel'] = _id(relation)
    elif entity is not None:
        data['entity'] = _id(entity)
    else:
        raise ValueError, 'supply either entity or relation'
    incol.insert(data)
Exemple #11
0
 def get_current_and_old_members(self):
     dt = now()
     cur, _all = set(), set()
     for rel in self.get_rrelated(how=None, deref_with=False):
         _all.add(rel['who'])
         if ((rel['until'] is None or rel['until'] >= dt) and
                 (rel['from'] is None or rel['from'] <= dt)):
             cur.add(rel['who'])
     return (cur, _all - cur)
Exemple #12
0
 def get_current_and_old_members(self):
     dt = now()
     cur, _all = set(), set()
     for rel in self.get_rrelated(how=None, deref_with=False):
         _all.add(rel['who'])
         if ((rel['until'] is None or rel['until'] >= dt)
                 and (rel['from'] is None or rel['from'] <= dt)):
             cur.add(rel['who'])
     return (cur, _all - cur)
Exemple #13
0
def generate_unix_map(giedo):
    ret = {'groups': {},
           'users': {}}
    dt_now = now()
    # Get all users
    ulut = dict()
    for u in Es.users():
        if not u.got_unix_user:
            continue
        ulut[u._id] = u
        ret['users'][str(u.name)] = {
                'full_name': u.full_name,
                'expire_date': DT_MIN.strftime('%Y-%m-%d')}
    member_relations_grouped = dict()
    for rel in Es.query_relations(_with=Es.by_name('leden'), until=dt_now):
        if rel['who'] not in member_relations_grouped:
            member_relations_grouped[rel['who']] = []
        member_relations_grouped[rel['who']].append(rel)
    for user_id, relations in member_relations_grouped.items():
        latest = max(relations, key=lambda x: x['until'])
        ret['users'][str(ulut[user_id].name)]['expire_date'] \
                = latest['until'].strftime('%Y-%m-%d')

    # Get all groups and create a look-up-table for group membership
    gs = tuple(Es.groups())
    mrels = Es.query_relations(how=None, _with=gs, _from=dt_now,
                until=dt_now)
    mlut = dict()
    for g in gs:
        mlut[g._id] = []
    for mrel in mrels:
        mlut[mrel['with']].append(mrel['who'])
    # Flatten out group membership.  For instance: if Giedo is in Kasco
    # and Kasco is in Boekenlezers, then Giedo is also in the Boekenlezers
    # unix group.
    # But first split the mlut graph into a group and a non-group subgraph.
    mlut_g = {}     # { <group> : <members that are groups> }
    mlut_ng = {}    # { <group> : <members that are not groups> }
    for g_id in mlut:
        mlut_g[g_id] = [c for c in mlut[g_id] if c in mlut]
        mlut_ng[g_id] = [c for c in mlut[g_id] if c not in mlut]
    mlut_g_tc = tc(mlut_g)  # transitive closure
    # Generate the { <group> : <indirect non-group members> } graph
    memb_graph = {}
    for g in gs:
        if not g.got_unix_group:
            continue
        memb_graph[g._id] = set(mlut_ng[g._id])
        for h_id in mlut_g_tc[g._id]:
            memb_graph[g._id].update(mlut_ng[h_id])
    # Fill the return map
    for g in gs:
        if not g.got_unix_group:
            continue
        ret['groups'][str(g.name)] = [str(ulut[c].name)
                for c in memb_graph[g._id] if c in ulut]
    return ret
Exemple #14
0
 def is_related_with(self, whom, how=None):
     dt = now()
     how = None if how is None else _id(how)
     return rcol.find_one(
         {'who': _id(self),
          'how': how,
          'from': {'$lte': dt},
          'until': {'$gte': dt},
          'with': _id(whom)}, {'_id': True}) is not None
Exemple #15
0
def generate_unix_map(giedo):
    ret = {'groups': {},
           'users': {}}
    dt_now = now()
    # Get all users
    ulut = dict()
    for u in Es.users():
        if not u.got_unix_user:
            continue
        ulut[u._id] = u
        ret['users'][str(u.name)] = {
            'full_name': u.full_name,
            'expire_date': DT_MIN.strftime('%Y-%m-%d')}
    member_relations_grouped = dict()
    for rel in Es.query_relations(_with=Es.by_name('leden'), until=dt_now):
        if rel['who'] not in member_relations_grouped:
            member_relations_grouped[rel['who']] = []
        member_relations_grouped[rel['who']].append(rel)
    for user_id, relations in member_relations_grouped.items():
        latest = max(relations, key=lambda x: x['until'])
        ret['users'][str(ulut[user_id].name)]['expire_date'] = (
            latest['until'].strftime('%Y-%m-%d'))

    # Get all groups and create a look-up-table for group membership
    gs = tuple(Es.groups())
    mrels = Es.query_relations(how=None, _with=gs, _from=dt_now,
                               until=dt_now)
    mlut = dict()
    for g in gs:
        mlut[g._id] = []
    for mrel in mrels:
        mlut[mrel['with']].append(mrel['who'])
    # Flatten out group membership.  For instance: if Giedo is in Kasco
    # and Kasco is in Boekenlezers, then Giedo is also in the Boekenlezers
    # unix group.
    # But first split the mlut graph into a group and a non-group subgraph.
    mlut_g = {}     # { <group> : <members that are groups> }
    mlut_ng = {}    # { <group> : <members that are not groups> }
    for g_id in mlut:
        mlut_g[g_id] = [c for c in mlut[g_id] if c in mlut]
        mlut_ng[g_id] = [c for c in mlut[g_id] if c not in mlut]
    mlut_g_tc = tc(mlut_g)  # transitive closure
    # Generate the { <group> : <indirect non-group members> } graph
    memb_graph = {}
    for g in gs:
        if not g.got_unix_group:
            continue
        memb_graph[g._id] = set(mlut_ng[g._id])
        for h_id in mlut_g_tc[g._id]:
            memb_graph[g._id].update(mlut_ng[h_id])
    # Fill the return map
    for g in gs:
        if not g.got_unix_group:
            continue
        ret['groups'][str(g.name)] = [str(ulut[c].name)
                                      for c in memb_graph[g._id] if c in ulut]
    return ret
Exemple #16
0
 def add_note(self, what, by=None):
     dt = now()
     note = Note({
         'note': what,
         'on': self._id,
         'by': None if by is None else _id(by),
         'at': dt
     })
     note.save()
     return note
Exemple #17
0
    def cached_groups(self):
        """ The list of entities this user is None-related with.

        This field is cached. """
        if not hasattr(self, '__groups_cache'):
            dt = now()
            self.__groups_cache = [rel['with']
                for rel in self.get_related(
                    None, dt, dt, False, True, False)]
        return self.__groups_cache
Exemple #18
0
 def all_needing_reminder(cls):
     dt = now() + datetime.timedelta(days=7)
     events = [e['_id'] for e in ecol.find({'date': {'$lte': dt}})]
     for v in vcol.find({
             'reminder_needed': True,
             'event': {
                 '$in': events
             }
     }):
         yield cls.from_data(v)
Exemple #19
0
 def update_primary_telephone(self, new, save=True):
     """ Adds @new as new and primary telephone number. """
     if 'telephones' not in self._data:
         self._data['telephones'] = []
     addrs = self._data['telephones']
     dt = now()
     if addrs:
         addrs[0]['until'] = dt
     addrs.insert(0, {'number': new, 'from': dt, 'until': DT_MAX})
     if save:
         self.save()
Exemple #20
0
 def update_primary_email(self, new, save=True):
     """ Adds @new as new and primary e-mail address. """
     if 'emailAddresses' not in self._data:
         self._data['emailAddresses'] = []
     addrs = self._data['emailAddresses']
     dt = now()
     if addrs:
         addrs[0]['until'] = dt
     addrs.insert(0, {'email': new, 'from': dt, 'until': DT_MAX})
     if save:
         self.save()
Exemple #21
0
 def add_note(self, what, by=None):
     dt = now()
     Note({
         'note': what,
         'on': self._id,
         'open': True,
         'by': None if by is None else _id(by),
         'at': dt,
         'closed_by': None,
         'closed_at': None
     }).save()
Exemple #22
0
    def cached_groups(self):
        """ The list of entities this user is None-related with.

        This field is cached. """
        if not hasattr(self, '_groups_cache'):
            dt = now()
            self._groups_cache = [
                rel['with']
                for rel in self.get_related(None, dt, dt, False, True, False)
            ]
        return self._groups_cache
Exemple #23
0
def generate_mailman_changes(giedo):
    todo = {'create': [], 'add': {}, 'remove': {}}
    # TODO mm_groups and mm_rels
    # Get the groups that need a mailing list and the members of those
    # groups.
    dt_now = now()
    mm_groups = [g for g in Es.groups() if g.got_mailman_list and g.name]
    mm_rels = Es.query_relations(_with=mm_groups,
                                 how=None,
                                 _from=dt_now,
                                 until=dt_now,
                                 deref_who=True)
    # Get the current mailing list membersip
    ml_membership = giedo.hans.send({'type': 'maillist-get-membership'})

    # membership_to_check will contain the current membership of the
    # mailinglists for which there are groups.  We will remove users
    # from membership_to_check if we see these users are in the groups.
    # In the end membership_to_check contains the stray users.
    membership_to_check = {}
    gid2name = dict()
    # Find the current members of the mailing lists and find which
    # mailing lists are missing.
    for g in mm_groups:
        name = str(g.name).encode()
        gid2name[g._id] = name
        if name in ml_membership:
            membership_to_check[name] = set(ml_membership[name])
        else:
            todo['create'].append((name, six.text_type(g.humanName)))
            membership_to_check[name] = set()

    # Check which memberships are missing in the current mailing lists
    for rel in mm_rels:
        em = rel['who'].canonical_email.encode()
        gname = gid2name[rel['with']]
        if em not in membership_to_check[gname]:
            if gname not in todo['add']:
                todo['add'][gname] = []
            todo['add'][gname].append(em)
        else:
            membership_to_check[gname].remove(em)

    # Check which memberships are superfluous in the current mailing lists
    for n in ml_membership:
        if n not in membership_to_check:
            logging.warning("Unaccounted e-maillist %s" % n)
            continue
        for em in membership_to_check[n]:
            if n not in todo['remove']:
                todo['remove'][n] = []
            todo['remove'][n].append(em)
    return todo
Exemple #24
0
def _entity_detail(request, e):
    def _cmp(x,y):
        r = Es.relation_cmp_until(y,x)
        if r: return r
        r = cmp(unicode(x['with'].humanName),
                unicode(y['with'].humanName))
        if r: return r
        r = cmp(unicode(x['how'].humanName) if x['how'] else None,
            unicode(y['how'].humanName) if y['how'] else None)
        if r: return r
        return Es.relation_cmp_from(x,y)
    def _rcmp(x,y):
        r = Es.relation_cmp_until(y,x)
        if r: return r
        r = cmp(unicode(x['how'].humanName) if x['how'] else None,
            unicode(y['how'].humanName) if y['how'] else None)
        if r: return r
        r = cmp(unicode(x['who'].humanName),
                unicode(y['who'].humanName))
        if r: return r
        return Es.relation_cmp_from(x,y)
    related = sorted(e.get_related(), cmp=_cmp)
    rrelated = sorted(e.get_rrelated(), cmp=_rcmp)
    for r in chain(related, rrelated):
        r['may_end'] = Es.user_may_end_relation(request.user, r)
        r['id'] = r['_id']
        r['until_year'] = (None if r['until'] is None else
                    Es.date_to_year(r['until']))
        r['virtual'] = Es.relation_is_virtual(r)
    tags = [t.as_primary_type() for t in e.get_tags()]
    ctx = {'related': related,
           'rrelated': rrelated,
           'now': now(),
           'tags': sorted(tags, Es.entity_cmp_humanName),
           'object': e}
    # Is request.user allowed to add (r)relations?
    if ('secretariaat' in request.user.cached_groups_names
            and (e.is_group or e.is_user)):
        groups = [g for g in Es.groups() if not g.is_virtual]
        groups.sort(cmp=lambda x,y: cmp(unicode(x.humanName),
                        unicode(y.humanName)))
        users = sorted(Es.users(), cmp=Es.entity_cmp_humanName)
        brands = sorted(Es.brands(), cmp=Es.entity_cmp_humanName)
        ctx.update({'users': users,
                'brands': brands,
                'groups': groups,
                'may_add_related': True,
                'may_add_rrelated': True})
    if e.is_tag:
        ctx.update({'tag_bearers': sorted(e.as_tag().get_bearers(),
                        cmp=Es.entity_cmp_humanName)})
    return ctx
Exemple #25
0
def may_manage_planning(user):
    if user is None:
        return False
    if not hasattr(user, 'cached_groups_names'):
        # e.g. AnonymousUser
        return False
    if user.cached_groups_names & PLANNER_GROUPS:
        return True
    dt = now()
    if len(list(user.get_related(Es.by_name('!brand-planner'), dt, dt, False, False, False))):
        # The user has any role 'planner' so they may manage it.
        return True
    return False
Exemple #26
0
 def update_primary_email(self, new, save=True):
     """ Adds @new as new and primary e-mail address. """
     if 'emailAddresses' not in self._data:
         self._data['emailAddresses'] = []
     addrs = self._data['emailAddresses']
     dt = now()
     if addrs:
         addrs[0]['until'] = dt
     addrs.insert(0, {'email': new,
              'from': dt,
              'until': DT_MAX})
     if save:
         self.save()
Exemple #27
0
def end_rel(who, _with, how, at=None):
    """ Ends a relation given by names.

    For instance: end_rel('giedo', 'leden', None, '2012-04-09') """
    who = Es.id_by_name(who)
    _with = Es.id_by_name(_with)
    how = (Es.ecol.find_one({'sofa_suffix': how})['_id']
           if how is not None else None)
    at = str_to_date(at) if at is not None else now()
    Es.rcol.update({'who': who,
                    'with': _with,
                    'how': how,
                    'until': DT_MAX}, {'$set': {'until': at}})
Exemple #28
0
 def update_primary_telephone(self, new, save=True):
     """ Adds @new as new and primary telephone number. """
     if 'telephones' not in self._data:
         self._data['telephones'] = []
     addrs = self._data['telephones']
     dt = now()
     if addrs:
         addrs[0]['until'] = dt
     addrs.insert(0, {'number': new,
              'from': dt,
              'until': DT_MAX})
     if save:
         self.save()
Exemple #29
0
def _group_detail(request, group):
    ctx = _entity_detail(request, group)
    isFreeToJoin = group.has_tag(Es.id_by_name("!free-to-join", True))
    rel_id = None
    if isFreeToJoin:
        dt = now()
        rel = list(Es.query_relations(request.user, group, None, dt, dt, False, False, False))
        assert len(rel) <= 1
        for r in rel:
            rel_id = r["_id"]
    ctx.update(
        {"isFreeToJoin": group.has_tag(Es.by_name("!free-to-join")), "request": request, "relation_with_group": rel_id}
    )
    return render_to_response("leden/group_detail.html", ctx, context_instance=RequestContext(request))
Exemple #30
0
def generate_mailman_changes(giedo):
    todo = {'create': [], 'add': {}, 'remove': {}}
    # TODO mm_groups and mm_rels
    # Get the groups that need a mailing list and the members of those
    # groups.
    dt_now = now()
    mm_groups = [g for g in Es.groups() if g.got_mailman_list and g.name]
    mm_rels = Es.query_relations(_with=mm_groups, how=None, _from=dt_now,
                                 until=dt_now, deref_who=True)
    # Get the current mailing list membersip
    ml_membership = giedo.hans.send({'type': 'maillist-get-membership'})

    # membership_to_check will contain the current membership of the
    # mailinglists for which there are groups.  We will remove users
    # from membership_to_check if we see these users are in the groups.
    # In the end membership_to_check contains the stray users.
    membership_to_check = {}
    gid2name = dict()
    # Find the current members of the mailing lists and find which
    # mailing lists are missing.
    for g in mm_groups:
        name = str(g.name).encode()
        gid2name[g._id] = name
        if name in ml_membership:
            membership_to_check[name] = set(ml_membership[name])
        else:
            todo['create'].append((name, six.text_type(g.humanName)))
            membership_to_check[name] = set()

    # Check which memberships are missing in the current mailing lists
    for rel in mm_rels:
        em = rel['who'].canonical_email.encode()
        gname = gid2name[rel['with']]
        if em not in membership_to_check[gname]:
            if gname not in todo['add']:
                todo['add'][gname] = []
            todo['add'][gname].append(em)
        else:
            membership_to_check[gname].remove(em)

    # Check which memberships are superfluous in the current mailing lists
    for n in ml_membership:
        if n not in membership_to_check:
            logging.warning("Unaccounted e-maillist %s" % n)
            continue
        for em in membership_to_check[n]:
            if n not in todo['remove']:
                todo['remove'][n] = []
            todo['remove'][n].append(em)
    return todo
Exemple #31
0
 def _sync_villanet(self):
     ret = self.villanet_request({'action': 'listUsers'})
     if not ret[0]:
         return
     ret = json.loads(ret[1])
     users = dict()
     ulut = dict()
     for u in Es.users():
         ulut[u._id] = str(u.name)
     member_relations_grouped = dict()
     for rel in Es.query_relations(_with=Es.by_name('leden'), until=now()):
         if rel['who'] not in member_relations_grouped:
             member_relations_grouped[rel['who']] = []
         member_relations_grouped[rel['who']].append(rel)
     for user_id, relations in member_relations_grouped.items():
         latest = max(relations, key=lambda x: x['until'])
         users[ulut[user_id]] = latest['until'].strftime('%Y-%m-%d')
     vn = set(ret.keys())
     kn = set(users.keys())
     dt_max = settings.DT_MAX.strftime('%Y-%m-%d')
     for name in kn - vn:
         data = {
             'username': name,
             'password': self.villanet_encrypt_password(pseudo_randstr(16)),
         }
         if users[name] != dt_max:
             data['till'] = users[name]
         pc = Es.PushChange({
             'system': 'villanet',
             'action': 'addUser',
             'data': data
         })
         pc.save()
     for name in vn - kn:
         logging.info("Stray user %s" % name)
     for name in vn & kn:
         remote = (ret[name]['till'][:10]
                   if ret[name]['till'] is not None else '')
         local = users[name] if users[name] != dt_max else ''
         if remote != local:
             pc = Es.PushChange({
                 'system': 'villanet',
                 'action': 'changeUser',
                 'data': {
                     'username': name,
                     'till': local
                 }
             })
             pc.save()
     self.push_changes_event.set()
Exemple #32
0
def planning_view(request):
    if 'lookbehind' in request.GET:
        lookbehind = int(request.GET['lookbehind'])
    else:
        lookbehind = 1
    pools = list(Pool.all())
    poolid2index = dict()
    poolids = set()
    for pool in pools:
        poolids.add(_id(pool))
    # TODO reduce number of queries
    event_entities = list(Event.all_since_datetime(date_to_midnight(now())
            - datetime.timedelta(days=lookbehind)))
    used_pools = set()
    for e in event_entities:
        for v in e.vacancies():
            used_pools.add(v.pool_id)
    pools_tpl = []
    i = 0
    for pool in pools:
        if _id(pool) not in used_pools:
            continue
        poolid2index[pool._id] = i
        pools_tpl.append(pool)
        i += 1
    events = list()
    for e in event_entities:
        ei = {  'id': _id(e),
                'name': e.name,
                'datetime': e.date,
                'kind': e.kind,
            'vacancies': dict()}
        for index in poolid2index.values():
            ei['vacancies'][index] = list()
        for v in e.vacancies():
            ei['vacancies'][poolid2index[v.pool_id]].append({
                'begin': v.begin,
                'begin_time': v.begin_time,
                'end_time': v.end_time,
                'assignee': v.assignee.humanName
                        if v.assignee else "?"})
        for index in poolid2index.values():
            ei['vacancies'][index].sort(key=lambda x: x['begin'])
        events.append(ei)
    events.sort(key=lambda x: x['datetime'])
    return render_to_response('planning/overview.html',
            {'events': events,
             'pools': pools_tpl},
            context_instance=RequestContext(request))
Exemple #33
0
 def is_related_with(self, whom, how=None):
     dt = now()
     how = None if how is None else _id(how)
     return rcol.find_one(
         {
             'who': _id(self),
             'how': how,
             'from': {
                 '$lte': dt
             },
             'until': {
                 '$gte': dt
             },
             'with': _id(whom)
         }, {'_id': True}) is not None
Exemple #34
0
 def update_study(self, study, institute, number, save=True):
     """ Adds (study, institute, number) as new and primary. """
     if 'studies' not in self._data:
         self._data['studies'] = []
     studies = self._data['studies']
     dt = now()
     if studies:
         studies[0]['until'] = dt
     studies.insert(0, {'study': _id(study),
                'institute': _id(institute),
                'number': number,
                'from': dt,
                'until': DT_MAX})
     if save:
         self.save()
Exemple #35
0
def _group_detail(request, group):
    ctx = _entity_detail(request, group)
    isFreeToJoin = group.has_tag(Es.id_by_name('!free-to-join', True))
    rel_id = None
    if isFreeToJoin:
        dt = now()
        rel = list(Es.query_relations(request.user, group, None,
                                      dt, dt, False, False, False))
        assert len(rel) <= 1
        for r in rel:
            rel_id = r['_id']
    ctx.update({'isFreeToJoin': group.has_tag(Es.by_name('!free-to-join')),
                'request': request,
                'relation_with_group': rel_id})
    return render(request, 'leden/group_detail.html', ctx)
Exemple #36
0
def generate_mailman_changes(hans):
    todo = hans_pb2.ApplyChangesReq()
    # TODO mm_groups and mm_rels
    # Get the groups that need a mailing list and the members of those
    # groups.
    dt_now = now()
    mm_groups = [g for g in Es.groups() if g.got_mailman_list and g.name]
    mm_rels = Es.query_relations(_with=mm_groups, how=None, _from=dt_now,
                                 until=dt_now, deref_who=True)
    # Get the current mailing list membersip
    ml_membership = hans.GetMembership(hans_pb2.GetMembershipReq()).membership

    # membership_to_check will contain the current membership of the
    # mailinglists for which there are groups.  We will remove users
    # from membership_to_check if we see these users are in the groups.
    # In the end membership_to_check contains the stray users.
    membership_to_check = {}
    gid2name = dict()
    # Find the current members of the mailing lists and find which
    # mailing lists are missing.
    for g in mm_groups:
        name = str(g.name).encode()
        gid2name[g._id] = name
        if name in ml_membership:
            membership_to_check[name] = set(ml_membership[name].emails)
        else:
            todo.create.append(hans_pb2.ListCreateReq(
                name=name,
                humanName=six.text_type(g.humanName)))
            membership_to_check[name] = set()

    # Check which memberships are missing in the current mailing lists
    for rel in mm_rels:
        em = rel['who'].canonical_email.encode()
        gname = gid2name[rel['with']]
        if em not in membership_to_check[gname]:
            todo.add[gname].emails.append(em)
        else:
            membership_to_check[gname].remove(em)

    # Check which memberships are superfluous in the current mailing lists
    for n in ml_membership:
        if n not in membership_to_check:
            logging.warning("Unaccounted e-maillist %s" % n)
            continue
        for em in membership_to_check[n]:
            todo.remove[n].emails.append(em)
    return todo
Exemple #37
0
 def _sync_villanet(self):
     if not settings.VILLANET_SECRET_API_KEY:
         logging.warn("VILLANET_SECRET_API_KEY not set")
         return
     ret = self.villanet_request({'action': 'listUsers'})
     if not ret[0]:
         return
     ret = json.loads(ret[1])
     users = dict()
     ulut = dict()
     for u in Es.users():
         ulut[u._id] = str(u.name)
     member_relations_grouped = dict()
     for rel in Es.query_relations(_with=Es.by_name('leden'), until=now()):
         if rel['who'] not in member_relations_grouped:
             member_relations_grouped[rel['who']] = []
         member_relations_grouped[rel['who']].append(rel)
     for user_id, relations in member_relations_grouped.items():
         latest = max(relations, key=lambda x: x['until'])
         users[ulut[user_id]] = latest['until'].strftime('%Y-%m-%d')
     vn = set(ret.keys())
     kn = set(users.keys())
     dt_max = settings.DT_MAX.strftime('%Y-%m-%d')
     for name in kn - vn:
         data = {
                 'username': name,
                 'password': self.villanet_encrypt_password(
                     pseudo_randstr(16)),
             }
         if users[name] != dt_max:
             data['till'] = users[name]
         pc = Es.PushChange({'system': 'villanet', 'action': 'addUser',
             'data': data})
         pc.save()
     for name in vn - kn:
         logging.info("Stray user %s" % name)
     for name in vn & kn:
         remote = (ret[name]['till'][:10] if ret[name]['till'] is not None
                 else '')
         local = users[name] if users[name] != dt_max else ''
         if remote != local:
             pc = Es.PushChange({'system': 'villanet',
                 'action': 'changeUser', 'data': {
                     'username': name,
                     'till': local
                     }})
             pc.save()
     self.push_changes_event.set()
Exemple #38
0
def _group_detail(request, group):
    ctx = _entity_detail(request, group)
    isFreeToJoin = group.has_tag(Es.id_by_name('!free-to-join', True))
    rel_id = None
    if isFreeToJoin:
        dt = now()
        rel = list(Es.query_relations(request.user, group, None,
                                        dt, dt, False, False, False))
        assert len(rel) <= 1
        for r in rel:
            rel_id = r['_id']
    ctx.update({'isFreeToJoin': group.has_tag(Es.by_name('!free-to-join')),
        'request': request,
        'relation_with_group': rel_id})
    return render_to_response('leden/group_detail.html', ctx,
            context_instance=RequestContext(request))
Exemple #39
0
def may_manage_planning(user):
    if user is None:
        return False
    if not hasattr(user, 'cached_groups_names'):
        # e.g. AnonymousUser
        return False
    if user.cached_groups_names & PLANNER_GROUPS:
        return True
    dt = now()
    if len(
            list(
                user.get_related(Es.by_name('!brand-planner'), dt, dt, False,
                                 False, False))):
        # The user has any role 'planner' so they may manage it.
        return True
    return False
Exemple #40
0
 def update_address(self, street, number, _zip, city, save=True):
     """ Adds (street, number, _zip, city) as new and primary address. """
     if 'addresses' not in self._data:
         self._data['addresses'] = []
     addresses = self._data['addresses']
     dt = now()
     if addresses:
         addresses[0]['until'] = dt
     addresses.insert(0, {'street': street,
                          'number': number,
                          'zip': _zip,
                          'city': city,
                          'from': dt,
                          'until': DT_MAX})
     if save:
         self.save()
Exemple #41
0
def generate_mailman_changes(giedo):
    todo = {'create': [], 'add': {}, 'remove': {}}
    # TODO mm_groups and mm_rels
    # Get the groups that need a mailing list and the members of those
    # groups.
    dt_now = now()
    mm_groups = [g for g in Es.groups() if g.got_mailman_list and g.name]
    mm_rels = Es.query_relations(_with=mm_groups, how=None, _from=dt_now,
            until=dt_now, deref_who=True)
    # TODO do we want to cache these?
    # Get the current mailing lists
    ml_names = frozenset(Mailman.Utils.list_names())
    ml_members = dict()
    gid2name = dict()
    # Find the current members of the mailing lists and find which
    # mailing lists are missing.
    for g in mm_groups:
        gid2name[g._id] = str(g.name)
        if not str(g.name) in ml_names:
            todo['create'].append((str(g.name),
                    unicode(g.humanName)))
            c_ms = set([])
        else:
            c_ms = set([x[0] for x in
                Mailman.MailList.MailList(str(g.name),
                    lock=False).members.iteritems()])
        ml_members[str(g.name)] = c_ms
    # Check which memberships are missing in the current mailing lists
    for rel in mm_rels:
        em = rel['who'].canonical_email
        gname = gid2name[rel['with']]
        if not em in ml_members[gname]:
            if not gname in todo['add']:
                todo['add'][gname] = []
            todo['add'][gname].append(em)
        else:
            ml_members[gname].remove(em)
    # Check which memberships are superfluous in the current mailing lists
    for n in ml_names:
        if not n in ml_members:
            logging.warning("Unaccounted e-maillist %s" % n)
            continue
        for em in ml_members[n]:
            if not n in todo['remove']:
                todo['remove'][n] = []
            todo['remove'][n].append(em)
    return todo
Exemple #42
0
def end_rel(who, _with, how, at=None):
    """ Ends a relation given by names.

    For instance: end_rel('giedo', 'leden', None, '2012-04-09') """
    who = Es.id_by_name(who)
    _with = Es.id_by_name(_with)
    how = (Es.ecol.find_one({'sofa_suffix': how})['_id']
           if how is not None else None)
    at = str_to_date(at) if at is not None else now()
    Es.rcol.update({
        'who': who,
        'with': _with,
        'how': how,
        'until': DT_MAX
    }, {'$set': {
        'until': at
    }})
Exemple #43
0
 def update_study(self, study, institute, number, save=True):
     """ Adds (study, institute, number) as new and primary. """
     if 'studies' not in self._data:
         self._data['studies'] = []
     studies = self._data['studies']
     dt = now()
     if studies:
         studies[0]['until'] = dt
     studies.insert(
         0, {
             'study': _id(study),
             'institute': _id(institute),
             'number': number,
             'from': dt,
             'until': DT_MAX
         })
     if save:
         self.save()
Exemple #44
0
def planning_view(request):
    if 'lookbehind' in request.GET:
        lookbehind = int(request.GET['lookbehind'])
    else:
        lookbehind = 1
    pools = list(Pool.all())
    poolid2idx = dict()
    i = 0
    for pool in pools:
        poolid2idx[pool._id] = i
        i += 1
    events = list()
    # TODO reduce number of queries
    for e in Event.all_since_datetime(
            date_to_midnight(now()) - datetime.timedelta(days=lookbehind)):
        ei = {
            'name': e.name,
            'datetime': e.date,
            'kind': e.kind,
            'vacancies': dict()
        }
        for idx in poolid2idx.values():
            ei['vacancies'][idx] = list()
        for v in e.vacancies():
            ei['vacancies'][poolid2idx[v.pool_id]].append({
                'begin':
                v.begin,
                'begin_time':
                v.begin_time,
                'end_time':
                v.end_time,
                'assignee':
                v.assignee.get_user().humanName if v.assignee else "?"
            })
        for idx in poolid2idx.values():
            ei['vacancies'][idx].sort(key=lambda x: x['begin'])
        events.append(ei)
    events.sort(key=lambda x: x['datetime'])
    return render_to_response('planning/overview.html', {
        'events': events,
        'pools': pools,
        'poolcount': len(pools)
    },
                              context_instance=RequestContext(request))
Exemple #45
0
 def update_address(self, street, number, _zip, city, save=True):
     """ Adds (street, number, _zip, city) as new and primary address. """
     if 'addresses' not in self._data:
         self._data['addresses'] = []
     addresses = self._data['addresses']
     dt = now()
     if addresses:
         addresses[0]['until'] = dt
     addresses.insert(
         0, {
             'street': street,
             'number': number,
             'zip': _zip,
             'city': city,
             'from': dt,
             'until': DT_MAX
         })
     if save:
         self.save()
Exemple #46
0
def relation_begin(request):
    # TODO We should use Django forms, or better: use sweet Ajax
    d = {}
    for t in ('who', 'with', 'how'):
        if t not in request.POST:
            raise ValueError, "Missing attr %s" % t
        if t == 'how' and (not request.POST[t] or
                               request.POST[t] == 'null'):
            d[t] = None
        else:
            d[t] = _id(request.POST[t])
    if not Es.user_may_begin_relation(request.user, d['who'], d['with'],
                                                                d['how']):
        raise PermissionDenied
    # Check whether such a relation already exists
    dt = now()
    ok = False
    try:
        next(Es.query_relations(who=d['who'], _with=d['with'],
            how=d['how'], _from=dt, until=DT_MAX))
    except StopIteration:
        ok = True
    if not ok:
        raise ValueError, "This relation already exists"
    # Add the relation!
    Es.add_relation(d['who'], d['with'], d['how'], dt, DT_MAX)
    # Notify informacie
    if request.user._id == d['who']:
        Es.notify_informacie("%s heeft zich ingeschreven als %s %s" % (
                            request.user.full_name,
                            Es.by_id(d['how']).humanName if d['how'] else 'lid',
                            Es.by_id(d['with']).humanName.genitive))
    else:
        # TODO (rik) leave out 'als lid'
        Es.notify_informacie("%s is nu %s %s" % (
                            Es.by_id(d['who']).humanName,
                            Es.by_id(d['how']).humanName if d['how'] else 'lid',
                            Es.by_id(d['with']).humanName.genitive))
    giedo.sync_async(request)
    return redirect_to_referer(request)
Exemple #47
0
def check_email():
    dt_now = now()
    comm_ids = map(_id, Es.by_name('comms').get_bearers())
    list_ids = map(_id, Es.by_name('lists-opted').get_bearers())
    with open('check-email.template') as f:
        template_text = StringIO()
        for line in f:
            if line.endswith("\\\n"):
                template_text.write(line[:-2])
            else:
                template_text.write(line)
        templ = Template(template_text.getvalue())
    for m in args_to_users(sys.argv[1:]):
        rels = m.get_related()
        rels = sorted(rels,
                      cmp=lambda x, y: cmp(str(x['with'].humanName),
                                           str(y['with'].humanName)))
        comms = []
        lists = []
        others = []
        for rel in rels:
            if Es.relation_is_virtual(rel):
                continue
            if _id(rel['with']) in comm_ids:
                comms.append(rel)
            elif _id(rel['with']) in list_ids:
                lists.append(rel)
            else:
                others.append(rel)
        print m.name
        em = templ.render(
            Context({
                'u': m,
                'comms': comms,
                'lists': lists,
                'others': others
            }))
        send_mail('Controle Karpe Noktem ledenadministratie', em,
                  '*****@*****.**', [m.primary_email])
Exemple #48
0
def relation_begin(request):
    # TODO We should use Django forms, or better: use sweet Ajax
    d = {}
    for t in ('who', 'with', 'how'):
        if t not in request.POST:
            raise ValueError("Missing attr %s" % t)
        if t == 'how' and (not request.POST[t] or request.POST[t] == 'null'):
            d[t] = None
        else:
            d[t] = _id(request.POST[t])
    if not Es.user_may_begin_relation(request.user, d['who'], d['with'],
                                      d['how']):
        raise PermissionDenied

    # Check whether such a relation already exists
    dt = now()
    ok = False
    try:
        next(
            Es.query_relations(who=d['who'],
                               _with=d['with'],
                               how=d['how'],
                               _from=dt,
                               until=DT_MAX))
    except StopIteration:
        ok = True
    if not ok:
        messages.info(request, _("Deze relatie bestaat al"))
        return redirect_to_referer(request)

    # Add the relation!
    relation_id = Es.add_relation(d['who'], d['with'], d['how'], dt, DT_MAX)

    # Notify informacie
    # TODO (rik) leave out 'als lid'
    Es.notify_informacie('relation_begin', request.user, relation=relation_id)

    giedo.sync_async(request)
    return redirect_to_referer(request)
Exemple #49
0
def planning_view(request):
    if 'lookbehind' in request.GET:
        lookbehind = int(request.GET['lookbehind'])
    else:
        lookbehind = 1
    pools = list(Pool.all())
    poolid2idx = dict()
    i = 0
    for pool in pools:
        poolid2idx[pool._id] = i
        i += 1
    events = list()
    # TODO reduce number of queries
    for e in Event.all_since_datetime(date_to_midnight(now())
            - datetime.timedelta(days=lookbehind)):
        ei = {  'name': e.name,
                'datetime': e.date,
                'kind': e.kind,
            'vacancies': dict()}
        for idx in poolid2idx.values():
            ei['vacancies'][idx] = list()
        for v in e.vacancies():
            ei['vacancies'][poolid2idx[v.pool_id]].append({
                'begin': v.begin,
                'begin_time': v.begin_time,
                'end_time': v.end_time,
                'assignee': v.assignee.humanName
                        if v.assignee else "?"})
        for idx in poolid2idx.values():
            ei['vacancies'][idx].sort(key=lambda x: x['begin'])
        events.append(ei)
    events.sort(key=lambda x: x['datetime'])
    return render_to_response('planning/overview.html',
            {'events': events,
             'pools': pools,
             'poolcount': len(pools)},
            context_instance=RequestContext(request))
Exemple #50
0
def check_email():
    dt_now = now()
    comm_ids = map(_id, Es.by_name('comms').get_bearers())
    list_ids = map(_id, Es.by_name('lists-opted').get_bearers())
    with open('check-email.template') as f:
        template_text = StringIO()
        for line in f:
            if line.endswith("\\\n"):
                template_text.write(line[:-2])
            else:
                template_text.write(line)
        templ = Template(template_text.getvalue())
    for m in args_to_users(sys.argv[1:]):
        rels = m.get_related()
        rels = sorted(rels, cmp=lambda x,y: cmp(str(x['with'].humanName),
                            str(y['with'].humanName)))
        comms = []
        lists = []
        others = []
        for rel in rels:
            if Es.relation_is_virtual(rel):
                continue
            if _id(rel['with']) in comm_ids:
                comms.append(rel)
            elif _id(rel['with']) in list_ids:
                lists.append(rel)
            else:
                others.append(rel)
        print m.name
        em = templ.render(Context({
                        'u': m,
                        'comms': comms,
                        'lists': lists,
                        'others': others}))
        send_mail('Controle Karpe Noktem ledenadministratie',
                    em, '*****@*****.**',
                    [m.primary_email])
Exemple #51
0
def planning_manage(request, poolname):
    if not may_manage_planning(request.user):
        raise PermissionDenied
    pool = Pool.by_name(poolname)
    if pool is None:
        raise Http404
    if not pool.may_manage(request.user):
        raise PermissionDenied
    # TODO reduce number of queries
    events = dict()
    for e in Event.all_in_future():
        eid = _id(e)
        vacancies = list(e.vacancies(pool=pool))
        events[eid] = {
            'vacancies': vacancies,
            'date': e.date.date(),
            'name': e.name,
            'kind': e.kind,
            'id': eid
        }
        posted = False
        events[eid]['vacancies'].sort(key=lambda v: v.begin)
        if request.method == 'POST' and _id(request.POST['eid']) == eid:
            events[eid]['form'] = ManagePlanningForm(
                request.POST, pool=pool, vacancies=events[eid]['vacancies'])
            posted = True
        else:
            events[eid]['form'] = ManagePlanningForm(
                pool=pool, vacancies=events[eid]['vacancies'])
        if posted and events[eid]['form'].is_valid():
            for vacancy in events[eid]['vacancies']:
                worker = request.POST['shift_%s' % vacancy._id]
                if worker == '':
                    vacancy.assignee = None
                    vacancy.reminder_needed = True
                else:
                    if vacancy.assignee_id is None or \
                            _id(vacancy.assignee_id) != _id(worker):
                        delta = datetime.timedelta(days=5)
                        vacancy.reminder_needed = now() + delta < e.date
                        vacancy.assignee_id = _id(worker)
                vacancy.save()
    workers = pool.workers()
    # XXX het is cooler de shift dichtstbijzijnd aan de vacancy te
    # zoeken.  Stel dat iemand over een half-jaar al is ingepland
    # dan is dat niet zo boeiend.  Terwijl hij nu geen enkele
    # bardienst meer zou krijgen
    shifts = pool.last_shifts()
    for eid in events:
        for vacancy in events[eid]['vacancies']:
            vacancy.suggestions = list()
            workers_by_score = dict()
            for worker in workers:
                score = planning_vacancy_worker_score(vacancy, worker)
                if score not in workers_by_score:
                    workers_by_score[score] = list()
                workers_by_score[score].append(worker)
            found_scores = list(workers_by_score.keys())
            found_scores.sort(reverse=True)
            for score in found_scores:
                scorers = workers_by_score[score]
                shuffle(scorers)
                scorers.sort(key=lambda x: shifts[_id(x)]
                             if shifts[_id(x)] else DT_MIN.date())
                for scorer in scorers:
                    vacancy.suggestions.append({
                        'scorer': scorer,
                        'score': score
                    })

    events = list(events.values())
    events.sort(key=lambda e: e['date'])
    return render(request, 'planning/manage.html', {
        'events': events,
        'pool': pool
    })
Exemple #52
0
def planning_view(request):
    period = 'now'
    if request.GET.get('year') in {'past1', 'past2'}:
        period = request.GET['year']
    pools = list(Pool.all())
    poolid2index = dict()
    poolids = set()
    for pool in pools:
        poolids.add(_id(pool))
    # TODO reduce number of queries
    current = date_to_midnight(now() - datetime.timedelta(days=1))
    past1year = date_to_midnight(now() - datetime.timedelta(days=356))
    past2year = date_to_midnight(now() - datetime.timedelta(days=356 * 2))
    if period == 'now':
        start = current
        end = None
    elif period == 'past1':
        start = past1year
        end = current
    elif period == 'past2':
        start = past2year
        end = past1year
    event_entities = list(Event.all_in_period(start, end))
    used_pools = set()
    for e in event_entities:
        for v in e.vacancies():
            used_pools.add(v.pool_id)
    pools_tpl = []
    i = 0
    for pool in pools:
        if _id(pool) not in used_pools:
            continue
        poolid2index[pool._id] = i
        pools_tpl.append(pool)
        i += 1
    events = list()
    for e in event_entities:
        ei = {
            'id': _id(e),
            'name': e.name,
            'datetime': e.date,
            'kind': e.kind,
            'vacancies': dict()
        }
        for index in poolid2index.values():
            ei['vacancies'][index] = list()
        for v in e.vacancies():
            ei['vacancies'][poolid2index[v.pool_id]].append({
                'begin':
                v.begin,
                'begin_time':
                v.begin_time,
                'end_time':
                v.end_time,
                'assignee':
                v.assignee.humanName if v.assignee else "?"
            })
        for index in poolid2index.values():
            ei['vacancies'][index].sort(key=lambda x: x['begin'])
        events.append(ei)
    events.sort(key=lambda x: x['datetime'])
    return render(request, 'planning/overview.html', {
        'events': events,
        'pools': pools_tpl,
        'period': period
    })
Exemple #53
0
 def get_members(self):
     dt = now()
     return [r['who'] for r in self.get_rrelated(
             how=None, _from=dt, until=dt)]
Exemple #54
0
def notify_informacie(event, user, **props):
    data = {'when': now(), 'event': event}
    data['user'] = _id(user)
    for key, value in props.items():
        data[key] = _id(value)
    incol.insert(data)
Exemple #55
0
def end_relation(__id):
    dt = now()
    rcol.update({'_id': _id(__id)}, {'$set': {'until': dt}})
Exemple #56
0
 def all_in_future(cls):
     return cls.all_in_period(now(), None)
Exemple #57
0
def secr_add_user(request):
    if 'secretariaat' not in request.user.cached_groups_names:
        raise PermissionDenied
    if request.method == 'POST':
        form = AddUserForm(request.POST)
        if form.is_valid():
            fd = form.cleaned_data
            # First, create the entity.
            u = Es.User({
                'types': ['user'],
                'names': [fd['username']],
                'humanNames': [{
                    'human':
                    fd['first_name'] + ' ' + fd['last_name']
                }],
                'person': {
                    'titles': [],
                    'nick': fd['first_name'],
                    'given': None,
                    'family': fd['last_name'],
                    'dateOfBirth': date_to_dt(fd['dateOfBirth'])
                },
                'email':
                fd['email'],
                'address': {
                    'street': fd['addr_street'],
                    'number': fd['addr_number'],
                    'zip': fd['addr_zip'],
                    'city': fd['addr_city']
                },
                'telephone':
                fd['telephone'],
                'studies': [{
                    'institute': _id(fd['study_inst']),
                    'study': _id(fd['study']),
                    'from': DT_MIN,
                    'until': DT_MAX,
                    'number': fd['study_number']
                }],
                'is_active':
                True,
                'password':
                None
            })
            logging.info("Added user %s" % fd['username'])
            u.save()
            # Then, add the relations.
            groups = ['leden']
            if fd['incasso']:
                groups.append('incasso')
            else:
                groups.append('geen-incasso')
            for group in groups:
                Es.add_relation(u,
                                Es.id_by_name(group, use_cache=True),
                                _from=date_to_dt(fd['dateJoined']))
            for l in fd['addToList']:
                Es.add_relation(u,
                                Es.id_by_name(l, use_cache=True),
                                _from=now())
            # Let giedo synch. to create the e-mail adresses, unix user, etc.
            # TODO use giedo.async() and let giedo send the welcome e-mail
            giedo.sync()
            # Create a new password and send it via e-mail
            pwd = pseudo_randstr()
            u.set_password(pwd)
            giedo.change_password(str(u.name), pwd, pwd)
            render_then_email("leden/set-password.mail.html", u, {
                'user': u,
                'password': pwd
            })
            # Send the welcome e-mail
            render_then_email("leden/welcome.mail.html", u, {'u': u})
            Es.notify_informacie('adduser', request.user, entity=u._id)
            return HttpResponseRedirect(
                reverse('user-by-name', args=(fd['username'], )))
    else:
        form = AddUserForm()
    return render(request, 'leden/secr_add_user.html', {'form': form})
Exemple #58
0
def _entity_detail(request, e):
    related = sorted(
        e.get_related(),
        key=lambda x: (Es.DT_MIN - Es.relation_until(
            x), Es.entity_humanName(x['with']), Es.entity_humanName(x['how'])))
    rrelated = sorted(
        e.get_rrelated(),
        key=lambda x: (Es.DT_MIN - Es.relation_until(
            x), Es.entity_humanName(x['how']), Es.entity_humanName(x['who'])))
    for r in chain(related, rrelated):
        r['may_end'] = Es.user_may_end_relation(request.user, r)
        r['id'] = r['_id']
        r['until_year'] = (None if r['until'] is None or r['until'] >= now()
                           else Es.date_to_year(r['until']))
        r['virtual'] = Es.relation_is_virtual(r)
    tags = [t.as_primary_type() for t in e.get_tags()]

    # mapping of year => set of members
    year_sets = {}
    for r in rrelated:
        year = r['until_year']
        if year is None:
            year = 'this'

        if year not in year_sets:
            year_sets[year] = set()
        year_sets[year].add(r['who'])

    year_counts = {}
    for year in year_sets:
        year_counts[year] = len(year_sets[year])

    ctx = {
        'related': related,
        'rrelated': rrelated,
        'year_counts': year_counts,
        'now': now(),
        'tags': sorted(tags, key=Es.entity_humanName),
        'object': e,
        'chiefs': [],
        'pipos': [],
        'reps': []
    }
    for r in rrelated:
        if r['how'] and Es.relation_is_active(r):
            if str(r['how'].name) == '!brand-hoofd':
                r['hidden'] = True
                ctx['chiefs'].append(r)
            if str(r['how'].name) == '!brand-bestuurspipo':
                r['hidden'] = True
                ctx['pipos'].append(r)
            if str(r['how'].name) == '!brand-vertegenwoordiger':
                r['hidden'] = True
                ctx['reps'].append(r)
    # Is request.user allowed to add (r)relations?
    if ('secretariaat' in request.user.cached_groups_names
            and (e.is_group or e.is_user)):
        groups = [g for g in Es.groups() if not g.is_virtual]
        groups.sort(key=Es.entity_humanName)
        users = sorted(Es.users(), key=Es.entity_humanName)
        brands = sorted(Es.brands(), key=Es.entity_humanName)
        ctx.update({
            'users': users,
            'brands': brands,
            'groups': groups,
            'may_add_related': True,
            'may_add_rrelated': True,
            'may_tag': True,
            'may_untag': True
        })
    ctx['may_upload_smoel'] = e.name and request.user.may_upload_smoel_for(e)
    if e.is_tag:
        ctx.update({
            'tag_bearers':
            sorted(e.as_tag().get_bearers(), key=Es.entity_humanName)
        })

    # Check whether entity has a photo
    photo_size = e.photo_size
    if e.photo_size is not None:
        ctx.update({
            'hasPhoto': True,
            'photoWidth': photo_size[0],
            'photoHeight': photo_size[1]
        })
    return ctx